wiki/articles/pointer.md

2.5 KiB

Pointer

In a very simple sense, a pointer represents the memory address of a certain datum of a certain size in memory.

Here, the pointer `str` has the value of 0xdecade, therefore pointing to the memory at
that address (here a C string):

                   address | data
                 ----------+-------
uint16_t *n --->  0xdecadb | 0x27
                  0xdecadc | 0x7f
                  0xdecadd | 0xff
char *str ----->  0xdecade | 'H' 
                  0xdecadf | 'e'
                  0xdecae0 | 'l'
                  0xdecae1 | 'l'
                  0xdecae2 | 'o'
char *end ----->  0xdecae3 | 0x00
                  0xdecae4 | 0x27
                 ----------+------

char c = *str;        /* dereferencing, reading the first element */
char c4 = *(str + 4); /* with pointer arithmetic we can access the 4th element, 'o' */
char c4 = str[4];     /* array indexing is syntax sugar for *(arr + index) in C */

*str = 'h';       /* dereferencing, here we're modifying the first element */
str[0] = 'h';     /* equivalent in C */

In C (and almost all languages that have pointers), a pointer is an integer type, big enough to hold the entire valid address space of the host system.

/* This is a common pattern in embedded programming, usually the address being some
   kind of MMIO I/O address. */
char *str = (char *)0xdecade;

If you have an start and end pointer (this pointing past the end of the data) you can iterate over strings without an index counter:

char *s = "a looooooooooooong string"
char *send = s + 25;
int len = send - s; /* and the length, if you need it */

while (s < send) {
    putchar(*s);
    ++s; /* increment memory address */
}

Null pointer

A null pointer is a special case, which points to an invalid memory address (nowadays almost always 0). Usually a null pointer is meaningful only in hosted environments, in that case reading or writing from a null pointer will case a segmentation fault error, in which the OS will immediately kill the offending process. On embedded systems (without a MMU), a null pointer may represent a valid memory address. On C the expression (void *)0 is guaranteed to always produce a null pointer, even if the actual null pointer address is not zero.

Function pointers

Function pointers are more special. On most systems, just like a regular pointer, a function pointer is simply a memory address to the start of the function code. In some weird architectures like Itanium it is a pair of two addresses. Formally in C, dereferencing a function pointer is undefined behavior.