% lec 1: pointers # administrivia - ex0 solution posted; ex1 due Fri 11a; hw0 due next Tue 11p - use discussion board when possible - email `cse333-staff@cs` when needed - _not_ individual staff # self-exercise (lec 0) ```c unsigned char c = -1; int status = c; if (status == -1) printf("error!\n"); ``` . . . `ret == -1` is always _false_! bug found in Linux/ffmpeg/... # today's plan - recap from CSE 351: - [memory & data](http://courses.cs.washington.edu/courses/cse351/14au/lectures/02-memory_14au.pdf) - [virtual memory](http://courses.cs.washington.edu/courses/cse351/14au/lectures/10-virtualmem_14au.pdf) # pointer type - ` *` - examples: `int *`, `char *`, `void *`, `int **` - a value that represents a memory address # pointer dereference read from memory address p ```c int a = *p; ``` write to memory address p ```c int a = ...; *p = a; ``` undefined if out of bounds (buffer overflow) # example ```c #include int main(void) { int x = 42; int *p = &x; int **pp = &p; printf("%p %p %p\n", p, pp, &pp); } ``` `&x` is the address of variable `x` . . . output may vary due to [address space layout randomization][ASLR] [ASLR]: http://en.wikipedia.org/wiki/Address_space_layout_randomization # example: call-by-value ```c void update_status(int status) { status = -1; } ``` caller: ```c int st = 0; update_status(st); assert(st == 0); ``` # example: call-by-reference ```c void update_status(int *status) { *status = -1; } ``` caller: ```c int st = 0; update_status(&st); assert(st == -1); ``` # pointer arithmetic - pointer `+` integer → pointer - example: `p + 1` - alternative: `&p[1]`, `&1[p]` - `p + 1` evaluates to ? - pointer `-` integer: shortcut for "pointer `+` (`-` integer)" - pointer `-` pointer # arrays & strings in C - arrays as pointers array style pointer style ------------ -------------- `int[]` `int *` `p[n]` `*(p + n)` - string: `'\0'`-terminated array see also: [The Most Expensive One-byte Mistake](http://queue.acm.org/detail.cfm?id=2010365) # null pointer > I call it my billion-dollar mistake. -- C.A.R. Hoare ```c int *p = NULL; if (p) { ... } /* if (p != NULL) */ if (!p) { ... } /* if (p == NULL) */ ``` . . . - dereferencing a null pointer is undefined in C! - _not_ always `NullPointerException` - can go worse than crash - examples: attacks to [Flash](http://www.inf.fu-berlin.de/groups/ag-si/compsec_assign/Dowd2008.pdf) and [the Linux kernel](http://lwn.net/Articles/342330/) # pointers from integers ```c uint16_t volatile *p = (uint16_t volatile *)0xdeadbeef; uint16_t a = *p; uint16_t b = *p; *p = 42; ``` often seen in kernel / embedded systems code # standard library functions `memcpy`: copy `n` bytes from `src` to `dst` see also `memmove`, `memcmp`, `memset`, `memchr`, ... ```c void * memcpy(void *restrict dst, const void *restrict src, size_t n); ``` - `const`: promise - `memcpy` won't change the content of `src` - `restrict`: requirements - `dst` and `src` must _not_ overlap * * * # what is a memory address? review [virtual memory](http://courses.cs.washington.edu/courses/cse351/14au/lectures/10-virtualmem_14au.pdf) # address space - abstraction - contiguous block of n bytes - addressable by offset in [0, n - 1] - interface - read(offset) → value - write(offset, value) # virtualization - hide physical details: `*p` - physical RAM - disk - device registers (CSE 451) - other machines' memory (CSE 550/551/552) - isolation # side note: strict aliasing ```c #include #include void foo(uint32_t *p32, uint64_t *p64) { *p32 = 0xdeadbeaf; *p64 = 0; printf("%" PRIx32 "\n", *p32); } int main(void) { uint64_t a; foo((uint32_t *)&a, &a); } ``` see also: [Type Punning, Strict Aliasing, and Optimization](http://blog.regehr.org/archives/959) # self-exercise: parsing - input parameters: pointer `s`, and the total length `len` of `s` - parse data starting from `s` - 4-byte header: integer `n`, little endian - followed by `n`-byte payload - followed by the rest of input - return value - pointer to the rest of input (i.e., skip header+payload) - or NULL if error (e.g., not enough input data to parse) ```c #include #include uint8_t *parse(uint8_t *s, uint32_t len) { ... } ```