diff --git a/clang.md b/clang.md index dda931065463ef2ecc7497c298d02be261fc9c8a..4906daaf360fbf6d8ca29d9aee2658dd1b80c148 100644 --- a/clang.md +++ b/clang.md @@ -227,8 +227,91 @@ int main(void) { - Anything that isn't false is true +## sizeof() Operator + +`sizeof(type)` returns number of **bytes** in object. By `C99` definition, `sizeof(char) == 1`. + +The operator returns a value in `size_t` defined in many headers like `<stddef.h>`, `<stdio.h>` etc. The actual type that holds the value is _implementation-defined_. + +However, `sizeof` **is not a function**! It is a **compile-time** operation. + ## Pointers in C Pointers are probably the single largest source of bugs in C, so be careful when you use them. +### Type of Pointers + +- Pointers are used to point to any kind of data, `int`, `char`, `struct` etc. +- `void *` is a type that can point to anything (generic pointer). +- You can have pointers to pointers: `int ****x`, declares x as pointer to a pointer to a pointer to a pointer of an `int`. +- You can have pointers to functions: `int (*fn) (void *, void*) = &foo;`, `fn` is a function that accepts two `void *` pointers and return an `int`. Use `(*fn)(x, y)` to invoke the function. + +### Casting and Casting Pointers + +You can cast (change the type) of basic C types which converts them: + +```c +int x; +float y; +y = (float) x; +``` + +For pointers it only changes **how they are interpreted**: + +```c +typedef struct { + int x; + int y; +} Pointer; + +void foo(void *v) { + ((Pointer *) v)->x = 24; +} +``` + +### Void Pointer + +We should also know that void pointers can be **casted** into any type of pointer. + +In C, library functions like `malloc`, `calloc` etc. return void pointers, which we can then cast in to any other type of pointers as we need: + +```c +#include <stdio.h> +#include <stdlib.h> + +int main() { + int num = 9; + int *ptr= (int *)malloc(sizeof(int)); + ptr = # + printf("ptr: %d", *ptr); + return 0; +} +``` + +However, void pointers have some limitations: + +- We can not **dereference** void pointers directly to access the values stored at those addresses +- Pointer arithmetic on void pointers is not possible, we have to first cast it into an appropriate type. + +### Pointer Arithmetic + +Valid pointer arithmetic: + +- Add an integer to a pointer: `ptr += 1;` +- Subtract 2 pointers (in the same array, evaluates to their distance apart in number of elements, with the type `ptrdiff_t`). +- Compare pointers (<, <=, ==, !=, >, >=) +- Compare pointers to `NULL` + +Everything else is illegal since it makes no sense: + +- Adding two pointers +- Multiplying pointers +- subtract pointers from integer + +#### `*p++` vs `(*p)++` + +These are common in many codebases, and the first time you see them, you might be confused. + +`x = *p++` is actually doing `x = *p; p = p + 1;`. +`x = (*p)++` is actually doing `x = *p; *p = *p + 1;`.