The Art of C Programming

##1. Principle

  • Array is NOT point
  • Avoid using unsafe api
  • Deeply understand point

##2. math

2.1 mod

if n%2k=x, then x=n&(2k-1)

2.2 even odd check

if the lowest bit of binary mode is 0, even number, otherwise odd.

2.3 multi

a*5 = a<<2+a

##3.structure

3.1 size

int arr[] = {1, 5, 3, 18, 107, 21, 88};

size of arr is sizeof(arr)/sizeof(arr[0])

struct _test_ {
    int a;
    double b;
    char c;
}

size of _test_ is sizeof(_test_)

##4. Puzzle

4.1 Print the numbers between 1 and 1000.

  • Add a rule: Don’t use any loops.
  • Add another rule: No recursions.
  • We can’t do that? OK. Please look at this one.
#include "stdio.h"
#define A(x) x;x;x;x;x;x;x;x;x;x;
int main (void){
  int n = 1;
  A(A(A(printf ("%d ", n++))));
  return 0;
}

4.2 swap two variables

a = a^b;
b = a^b;
a = a^b;

##5. What we need to avoid using?

  • gets –> fgets
  • scanf –> scanf_s sscanf
  • sprintf –> snprintf sprintf_s
  • strcpy –> strlcpy
  • strcat –> strlcat
  • strtok –> strtok_r

##6. v[index] and index[v] are the same

##7. use _Generic macro

#include <stdio.h>
#include <stdlib.h>

void printchar(char X) { printf("char: %c\n", X); }
void printint(int X) { printf("int: %d\n", X); }
void printfloat(float X) { printf("float: %f\n", X); }
void printdouble(double X) { printf("double: %lf\n", X); }
#define print(X) _Generic((X), \
                               char: printchar, \
                               int: printint, \
                               float: printfloat, \
                               double: printdouble)(X)

int main()
{
    print(1);
    print(1.2);
    print((char)'a');
    return 0;
}

GCC version don’t support _Generic macro currently, but clang work.
Compile this code with clang as clang test.c

##8. Reference