Post

C Linux Master Sheet

C interview cheatsheet of important questions. Make sure to revise the list daily.

Important C macros

Basic macros

1
2
3
4
5
6
7
8
9
10
11
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define ABS(x) ((x) < 0 ? -(x) : (x))
#define IS_POWER_OF_TWO(num) ((num) > 0 && ((num) & ((num) - 1)) == 0)
#define SWAP(x,y) (x ^= y ^=x ^= y)

#define SWAP(x,y,T) do { \
    T temp = (*x);\
    (*x) = (*y); \
    (*y) = temp; \
} while (0)

Bitwise macros

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#define SET_BIT(num, i) ((num) |= (1 << (i)))
#define CLEAR_BIT(num, i) ((num) &= ~(1 << (i)))
#define TOGGLE_BIT(num, i) ((num) ^= (1 << (i)))
#define CHECK_BIT(num, i) (((num) & (1 << (i))) != 0)

/* how to extract specific bits from, say, a 32-bit value */
#define EXTRACT_BITS(value, start, length) \
    (((value) >> (start)) & ((1U << (length)) - 1))

#define COUNT_SET_BITS(num) ({       \
    int _count = 0;                  \
    int _num = (num);                \
    while (_num) {                   \
        _num &= (_num - 1);          \
        _count++;                    \
    }                                \
    _count;                          \
})

Structure and type macros

1
2
3
4
#define SIZEOF(type) ((char *)(&type + 1) - (char *)(&type))

/* Find offset value of a member of a structure */
#define OFFSET_OF(type, member) ((size_t) &(((type *)0)->member))

List macros

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#define LIST_FOREACH_SAFE(head, node) \
    for (struct ListNode *node = (head), *__temp = (node ? node->next : NULL); \
         node != NULL; \
         node = __temp, __temp = (node ? node->next : NULL))

/* Not delete safe */     
#define LIST_FOREACH(head, node) \
    for (struct ListNode *node = (head); node != NULL; node = node->next)
    
/* Find length of LL */   
#define LIST_LENGTH(head, len) \
    do { \
        (len) = 0; \
        struct ListNode *node = (head); \
        while (node) { \
            (len)++; \
            node = node->next; \
        } \
    } while (0)

Other macros

1
#define IS_LITTLE_ENDIAN() ((*(char *)&(int){1}) == 1)

Function Pointers and Callbacks

Function Returning a function pointer usage

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>

typedef int (*OperationFunc)(char);

OperationFunc  additionFunction(int x)

// Function that returns a function pointer
int (*additionFunction(int x))(char) {
        int add(char c) {
        return c;
    }
    return add;
}

int main() {
    // Get the function pointer from the outer function
    int (*sumFunc)(char) = additionFunction(10); //This will call the function "additionFunction"
    
    // Call the function using the function pointer
    int result = sumFunc('A');
    
    printf("Result: %d\n", result); // Output: Result: 85 (ASCII value of 'A' is 65, 10 + 65 = 75)
    
    return 0;
}

Callback example programs to register ops

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>

typedef struct sample_ops {
    int data;
    void (*print)(int);
} sample_ops;

void printer(int a) {
    printf("Print %d\n", a); // Added the missing argument a
}

int main() {
    // Write C code here
    static const sample_ops my_ops = {
        .data = 60, // Replaced ; with ,
        .print = printer
    };
    
    my_ops.print(brcmf_ops.data); 
    return 0;
}
 

Tricky Code snippets

Find Length of linked list

1
2
int len=0;
for (struct ListNode *i = head; i; i=i->next, len++);

💡 Only one variable can be declared in for loop init section. So we cant declare len there. In the second and third place holder of for loop, we can have multiple statements separated by comma.

2D Array Allocation and Free

💡 dp[0][0] conversion to *((dp+0)+0)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <stdio.h>
#include <stdlib.h>

int main() {
    int rows = 3, cols = 4;
    int** array = malloc(rows * sizeof(int*)); // Allocate memory for row pointers

    if (array == NULL) {
        perror("Memory allocation failed");
        return 1;
    }

    for (int i = 0; i < rows; i++) {
        array[i] = malloc(cols * sizeof(int)); // Allocate memory for each row
        if (array[i] == NULL) {
            perror("Memory allocation failed");
            return 1;
        }
    }

    // Access elements
    array[1][2] = 42; // Example usage
    printf("Value at array[1][2]: %d\n", array[1][2]);

    // Free memory
    for (int i = 0; i < rows; i++) {
        free(array[i]); // Free each row
    }
    free(array); // Free the row pointers

    return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include <stdlib.h>

int main() {
    int rows = 3, cols = 4;
    int* array = malloc(rows * cols * sizeof(int)); // Single block for all elements

    if (array == NULL) {
        perror("Memory allocation failed");
        return 1;
    }

    // Access elements using index calculations
    array[1 * cols + 2] = 42; // Equivalent to array[1][2] in a "normal" 2D array
    printf("Value at array[1][2]: %d\n", array[1 * cols + 2]);

    // Free memory
    free(array);

    return 0;
}

Mutex, Semaphore and Spinlock

**Semaphore**: Use a semaphore when you (thread) want to sleep till some other thread tells you to wake up. Semaphore ‘down’ happens in one thread (producer) and semaphore ‘up’ (for same semaphore) happens in another thread (consumer) e.g.: In producer-consumer problem, producer wants to sleep till at least one buffer slot is empty - only the consumer thread can tell when a buffer slot is empty.

**Mutex**: Use a mutex when you (thread) want to execute code that should not be executed by any other thread at the same time. Mutex ‘down’ happens in one thread and mutex ‘up’ must happen in the same thread later on. e.g.: If you are deleting a node from a global linked list, you do not want another thread to muck around with pointers while you are deleting the node. When you acquire a mutex and are busy deleting a node, if another thread tries to acquire the same mutex, it will be put to sleep till you release the mutex.

**Spinlock**: Use a spinlock when you really want to use a mutex but your thread is not allowed to sleep. e.g.: An interrupt handler within OS kernel must never sleep. If it does the system will freeze / crash. If you need to insert a node to globally shared linked list from the interrupt handler, acquire a spinlock - insert node - release spinlock

Complex Declarations

Variable Declarations

1
2
3
4
5
6
7
8
1. int p; // An integer
2. int p[5]; // An array of 5 integers
3. int *p; // A pointer to an integer
4. int *p[10]; // An array of 10 pointers to integers
5. int **p; // A pointer to a pointer to an integer
6. int (*p)[3]; // A pointer to an array of 3 integers
7. int (*p)(char *); // A pointer to a function a that takes an integer
8. int (*p[5])(int); // An array of 5 pointers to functions that take an integer argument and return an integer

Single, Double and Triple Pointers with type qualifier

var declerations

Pointer to Array

1
int (*arr)[10];

Array of pointers

1
int *p[10];
1
2
3
int array[5][13];  // A 2D array with 5 rows and 13 columns
int (*eaytb)[13];  // Pointer to an array of 13 integers
eaytb = array;     // Pointing eaytb to the first row of the array

In this case, eaytb can be used to access the rows of the array. For instance, (*eaytb)[0] would give you the first row of the array, while (*eaytb)[1] would give you the second row, and so on.

C Basic Data Type Sizes and Format Specifiers

Data Type Memory (bytes) Range Format Specifier
short int 2 -32,768 to 32,767 %hd
unsigned short int 2 0 to 65,535 %hu
unsigned int 4 0 to 4,294,967,295 %u
int 4 -2,147,483,648 to 2,147,483,647 %d
long int 4 -2,147,483,648 to 2,147,483,647 %ld
unsigned long int 4 0 to 4,294,967,295 %lu
long long int 8 -(2^63) to (2^63)-1 %lld
unsigned long long int 8 0 to 18,446,744,073,709,551,615 %llu
signed char 1 -128 to 127 %c
unsigned char 1 0 to 255 %c
float 4 - %f
double 8 - %lf
long double 12 - %Lf

undefined

This post is licensed under CC BY 4.0 by the author.