Download presentation
Presentation is loading. Please wait.
Published byRolf Carpenter Modified over 9 years ago
1
Chapter 0.2 – Pointers and Memory
2
Type Specifiers const may be initialised but not used in any subsequent assignment common and useful volatile lookup the value of the variable on every single access, do not cache, store in a register, or use in optimisation used for memory mapping implementation dependent; no required semantics sometimes broken restrict Applied to a pointer indicates that the pointer is the only way to access the contents of the address improves optimization by preventing pointer aliasing atomic It's new and I don't really know what it does... Research suggests it can be used to somewhat cause a type or function to be atomic with respect to pre-emption
3
Strings In C, a string is nothing more than an array of characters. There is no field to store the length or any other data about the string. To mark the end of the string, a NULL value (i.e., all bits zero) is used. String library functions expect there to be a terminating NULL character. Because a string is an array, I'm going to ignore them when talking about memory and only discuss arrays.
4
Memory Management C is nothing but glorified assembly language To program in C effectively, one needs an understanding of: a. the memory model b. calling conventions Three basic ideas: 1. Static memory – things that don't change 2. Stack memory – things associated with function calls 3. Heap memory – globals, runtime allocation, etc.
5
Basic Memory Model
6
The Stack Every function call creates a stack frame that contains: 1. Arguments (values for parameters) 2. Return address 3. Context (saved register values) 4. Local variables Val/Address Arg 2: EBP + 12 Val/Address Arg 1: EBP + 8 Return Address Old/Saved EBP Local Variable 1: EBP - 4 Local Variable 2: EBP - 8 EAX (saved) … EDX (saved) Empty Space
7
Stack Storage The stack stores words (i.e., 64 bit values that can fit in a register ) Anything that can't fit on the stack is generally stored in the heap and it's address put on the stack Thus, we have to know where something is located to know if we have a value or an address
8
Storage Classes We can somewhat control where things are stored using storage classes auto : give the variable automatic storage on the stack; can only be used in functions register : try to keep the variable in a register; may by ignored; & cannot be used on register variables static inside functions, the variable retains it value between function calls (heap variable, not stack) outside functions, it indicates a variable declaration cannot be linked to other compilation units (files) extern : declare the variable; storage will be defined elsewhere and location determined at link time
9
Calling Conventions We put arguments (values for function parameters) on the stack when we call a function. Call by Value: We are putting a value (e.g., int, float, char) on the stack. Call by Reference: We are putting the address of the value(s) on the stack. The value is somewhere else (possibly the heap).
10
Arrays Arrays are kept in heap storage. The stack only ever stores the address. A pointer is a variable that stores an address. To manipulate arrays, we can offset from the base address using [] notation to obtain a value. We can also use the pointer directly and we can make pointers for non-arrays if desired.
11
Syntax Variables can be declared as pointer by prefixing them with *. int *x; Pointers can be dereferenced – that is, the value from the stored address is obtained. int z = *x; The address of something can be obtained by prefixing it with &. x = &argc; NOTE: It is bad if you take the address of something on the stack that can go away!
12
Pointers int x = 5; int *p; p = &x; printf ("%d %d", x, *p); * := LHS, "is a pointer" := RHS, "take value of" & := "take address of"
13
Example int x = 1, y = 2, z[10]; int *ip; /* ip is pointer to integer */ ip = &x; /* ip points to x */ y = *ip; /* y is now 1, the value in x */ *ip = 0; /* x is now 0 */ ip = &z[0]; /* ip points to z[0] */ *ip = y; /* z[0] now 1, the value in y */
14
Why we need pointers... void swap (int x, int y) { int tmp = x; x = y; y = tmp; } x and y are on the stack and use call by value This function swaps the values of two stack variables that go away when the function returns causing x, y to be deleted.
15
Using Pointers void swap (int *px, int *py) { int tmp = *px; *px = *py; *py = tmp; } int x = 1, y = 2; swap (&x, &y);
16
Function Pointers There are no objects and methods However, we can pass a function around without using an object We simply pass the address of the function (since it's in memory as well) Function names, like array names, are actually addresses When using a function pointer we need to dereference the address to action the code
17
Example: Function Pointer #include void fun (int a) { printf("Value of a is %d\n", a); } int main () { /* Define and initialise a function pointer */ void (*fun_ptr)(int) = &fun; /* Invoke fun() using fun_ptr */ (*fun_ptr)(10); return 0; }
18
Function Pointers void bsearch ( const void *key, const void *base, size_t n, size_t size, int (*cmp)(const void *keyval, const void *datum) ); char data[256][64]; bsearch("tami",data,64*sizeof(char),256,strcmp); Notes: void* is typically used to mean "pointer to anything" size_t is the type of the integers that are returned by sizeof
19
Dynamic Memory Management We can put things on the heap at runtime For example we can request heap space into which we can read a file's contents We use malloc() to do memory allocation When the memory is no longer needed, we can use free() to release it for re-use Java provides a "garbage" collector to manage the heap for us... in C we do it ourselves.
20
Example: Dynamic Memory /* Allocate a pair of buffers */ char *buf1 = malloc(256 * sizeof (char)); char *buf2 = calloc(256, sizeof(char)); /* resize buf1 and “leak” buf2 */ buf2 = realloc(buf1, 128 * sizeof (char)); /* Cause a runtime error with a double free */ free(buf1), free(buf2);
21
Definitions and Declarations Declarations say something exists. They provide enough information so that the file can be compiled. Where the declared entity will be located is determined during linking. The mechanism is in place to support the individual compilation of files and is the basis of "header files" (which mostly store declarations) Definitions assign memory to something.
22
Complex Declarations char **argv pointer to pointer to char int (*daytab)[13] pointer to array[13] of int int *daytab[13] array[13] of pointer to int void *comp() function return pointer to void void (*comp)() pointer to function returning void
23
Insane Declarations char (*(*x())[])() function returning pointer to array[] of pointers to functions returning char char(*(*x[3])())[5] array[3] of pointers to functions returning pointer to array[5] of chars
24
Structures: Records for Data /* Method A: Not using typedef */ struct point { int x; int y; }; struct point origin = { 0, 0 }; /* Method B: Compressed version of method A */ struct point { int x; int y; } origin = { 0, 0 }; /* Method C: Using typedef */ typedef struct { int x; int y; } point_t; point_t origin = { 0, 0 };
25
Recursive Structures typedef struct node { char *data; struct node next; } node_t; node_t *list = malloc(sizeof(node_t)); list->data = “Meredith”; list->next = NULL; node_t *list2 = malloc(sizeof(node_t)); list2->data = “Tami”; list2->next = list;
26
Unions Unions are used to save memory The size of a union is equal to the size of the largest field It is up to the programmer to use the fields correctly union number { int ival; float fval; } n; n.ival = 1; printf(“%f\n”, n.fval); /* works, but not a cast */
27
Do you ?
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.