C Programming

Preprocessor Directives; Bitwise Operators

C-CAT

Preprocessor Directives

Macros

// Object-like macros (constants)
#define PI 3.14159
#define MAX_SIZE 100
#define NEWLINE '\n'

// Function-like macros
#define SQUARE(x) ((x) * (x))         // always parenthesize!
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define
ABS(x)    ((x) >= 0 ? (x) : -(x))
#define SWAP(a, b, type) { type temp = (a); (a) = (b); (b)
= temp; }

// Usage
printf("PI = %.5f\n", PI);            // 3.14159
printf("5^2 = %d\n", SQUARE(5));      // 25
printf("Max(3,7) = %d\n", MAX(3,7));  // 7

Conditional Compilation

#define DEBUG 1

#ifdef DEBUG
    printf("Debug: x = %d\n", x);  // only compiled if DEBUG is defined
#endif

// Include guard (prevent double inclusion)
#ifndef MYHEADER_H
#define MYHEADER_H

// ... header content ...

#endif  // MYHEADER_H

// Version-based compilation
#if defined(WIN32) || defined(_WIN32)
    // Windows-specific code
#elif defined(__linux__)
    // Linux-specific code
#elif defined(__APPLE__)
    // macOS-specific code
#endif

#include Directive

#include <stdio.h>      // System header (search in system paths)
#include "myheader.h"   // Local header (search in current directory first)

Bitwise Operators

Bitwise Operators Reference

OperatorNameOperation
&ANDBoth bits 1 → 1
``OR
^XORBits differ → 1
~NOTInvert all bits
<<Left ShiftShift bits left (multiply by 2^n)
>>Right ShiftShift bits right (divide by 2^n)
unsigned char a = 0b10110010;   // 178
unsigned char b = 0b01101100;   // 108

printf("a & b = %08b → %d\n", a & b, a & b);  // 00100000 = 32
printf("a | b = %08b → %d\n", a | b, a | b);  // 11111110 = 254
printf("a ^ b = %08b → %d\n", a ^ b, a ^ b);  // 11011110 = 222
printf("~a = %08b\n", (unsigned char)~a);       // 01001101 = 77
printf("a << 2 = %d\n", a << 2);               // 136 (shifted left 2)
printf("a >> 2 = %d\n", a >> 2);               // 44 (shifted right 2)

Bitwise Applications

int count_ones(unsigned int n) {
    int count = 0;
    while (n != 0) {
        count += n & 1;   // check LSB
        n >>= 1;           // shift right
    }
    return count;
}
// Alternative: __builtin_popcount(n)

// 2. Display number in binary format
void print_binary(unsigned int n) {
    for (int i =
31; i >= 0; i--) {
        printf("%d", (n >> i) & 1);
        if (i % 4 == 0) printf(" ");
// space every 4 bits
    }
    printf("\n");
}

// 3. Check even parity
int check_parity(unsigned char byte) {
    int count =
count_ones(byte);
    return (count % 2 == 0) ? 1 : 0;  // 1 = even parity, 0 = odd parity
}

// Set MSB to make even parity:
unsigned char ensure_even_parity(unsigned char byte) {
if (!check_parity(byte)) {
        byte |= 0x80;   // Set MSB (bit 7)
    }
    return byte;
}

// 4. Toggle case using XOR
// XOR with 32 toggles case for ASCII letters:
// 'A' = 65 =
0x41, 'a' = 97 = 0x61  (differ by bit 5 = 32)
char toggle_case(char c) {
    if (isalpha(c))
return c ^ 32;
    return c;
}

// 5. Swap using XOR - no temp variable needed
void xor_swap(int *a, int *b) {
    *a = *a ^
*b;
    *b = *a ^ *b;
    *a = *a ^ *b;
}

// 6. Set a bit
unsigned int set_bit(unsigned int n, int pos) {
    return n | (1 << pos);
}

// 7. Clear a bit
unsigned int clear_bit(unsigned int n, int pos) {
    return n & ~(1 <<
pos);
}

// 8. Toggle a bit
unsigned int toggle_bit(unsigned int n, int pos) {
    return n ^ (1 <<
pos);
}

// 9. Check a bit
int check_bit(unsigned int n, int pos) {
    return (n >> pos) & 1;
}

Continue learning

Related notes

Put this topic into timed practice

Open mock tests when you want full-exam pacing, or keep drilling in practice mode.