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)

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

pointer type

  • <type> *
    • examples: int *, char *, void *, int **
    • a value that represents a memory address

pointer dereference

read from memory address p

    int a = *p;

write to memory address p

    int a = ...;
    *p = a;

undefined if out of bounds (buffer overflow)

example

#include <stdio.h>
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

example: call-by-value

void update_status(int status)
{
    status = -1;
}

caller:

    int st = 0;
    update_status(st);
    assert(st == 0);

example: call-by-reference

void update_status(int *status)
{
    *status = -1;
}

caller:

    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

null pointer

I call it my billion-dollar mistake. – C.A.R. Hoare

    int *p = NULL;
    if (p) { ... }   /* if (p != NULL) */
    if (!p) { ... }  /* if (p == NULL) */
  • dereferencing a null pointer is undefined in C!
  • not always NullPointerException

pointers from integers

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, …

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

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

#include <inttypes.h>
#include <stdio.h>
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

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)
#include <stddef.h>
#include <stdint.h>
uint8_t *parse(uint8_t *s, uint32_t len) { ... }