to another pointer, they must be of the same type (or use a cast operator) To make code flexible, use a pointer of type void Can be assigned to any pointer type Any pointer type can be assigned to it Cannot be dereferenced (must cast it first)
type to know how to dereference (*) a pointer For integer pointers, the compiler knows that it refers to 4-bytes in memory, so it can get its value Since a void pointer can be any data type, the compiler cannot dereference it (without a cast)
data type void and an asterisk (*) void *genericPointer = NULL; You can assign a void pointer an address just like any “normal” pointer genericPointer = &variableName;
need to cast it to the appropriate data type, and add an asterisk (*) to the cast operator, and then dereference (*) it, as you would any “normal” pointer variableName = *((dataType *) voidPointer); Note that the inner parenthesis is the cast operator, and the outer parenthesis is regular parenthesis
on the runtime stack name value address number1 0xffbffa34 letter1 0xffbffa33 genericPointer 0xffbffa2c //point genericPointer to number1 genericPointer = &number1; 5 ‘A’ 0xffbffa34
then dereference to access value name value address number1 0xffbffa34 letter1 0xffbffa33 genericPointer 0xffbffa2c *((int *)genericPointer) = *((int *)genericPointer) * 13; 65 ‘A’ 0xffbffa34
to variable of any data type name value address number1 0xffbffa34 letter1 0xffbffa33 genericPointer 0xffbffa2c //point genericPointer to letter1 genericPointer = &letter1; 65 ‘A’ 0xffbffa33
pointer points to variable of any data type name value address number1 0xffbffa34 letter1 0xffbffa33 genericPointer 0xffbffa2c *((char *)genericPointer) = *((char *)genericPointer) + 13; 65 'N' 0xffbffa33
parameters in the function does NOT change the values of the actual parameters (arguments) Makes a copy of the actual parameters, so changes to the formal parameters in the function do not change the values of the actual parameters See example program: swap.c
function definition Adds formal parameters to stack from right to left, so that is why letter4 is listed before letter3 name value address letter1 0xffbffa37 letter2 0xffbffa36 letter4 0xffbffa10 letter3 0xffbffa0c 'A' 'Z' ‘Z' ‘A'
function definition Actual parameter values do NOT change name value address letter1 0xffbffa37 letter2 0xffbffa36 letter4 0xffbffa10 letter3 0xffbffa0c temp 0xffbff9b7 'A' 'Z' ‘A' ‘Z' ‘A'
parameters in the function DOES change the values of the actual parameters (arguments) Makes a copy of the address of the actual parameters, so changes to the dereferenced (*) formal parameters in the function DO change the values of the actual parameters
before swap2() function call The address of each variable is the actual parameter name value address letter1 0xffbffa37 letter2 0xffbffa36 char letter1 = ‘A’; char letter2 = ‘Z’; swap2(&letter1,&letter2);
function definition Adds formal parameters to stack from right to left, so that is why letter6 is listed before letter5 name value address letter1 0xffbffa37 letter2 0xffbffa36 letter6 0xffbffa10 letter5 0xffbffa0c 'A' 'Z' 0xffbffa36 0xffbffa37
pointers as the actual parameters in a call by reference function call, as the pointers are storing the addresses of the original variables char *pointer1 = &letter1; char *pointer2 = &letter2; swap2(pointer1,pointer2);
almost interchangeable Because an array name is an address, an array name can be thought of as a constant pointer Because a pointer stores an address, pointers can be used to do array subscripting This is called “pointer/offset notation”
*(array + index); variable = *(pointer + index); The index is added to the address of the first (0th) element in the array, which is at a lower address in memory, while the rest of the array elements are stored at higher address in memory
and pointer to start of array, which is the first (0th) array element name value address array[3] 0xffbffa34 array[2] 0xffbffa30 array[1] 0xffbffa2c array[0] 0xffbffa28 pointer 0xffbffa24 40 30 20 10 0xffbffa28
the array name with array subscript notation, or pointer/offset notation //array subscript notation: printf(“%i\n”,array[0]); //pointer/offset notation: printf(“%i\n”,*(array+1));
use the pointer name with array subscript notation, or pointer/offset notation //array subscript notation: printf(“%i\n”,pointer[2]); //pointer/offset notation: printf(“%i\n”,*(pointer+3));
to declare and initialize strings looks the same and outputs the same But there are small different in how you use the strings later on in your program This can make your program not compile or crash
change the characters in the array Cannot change the array’s address Cannot change the length of the array (string) char array[] = “character array”;
Cannot change the characters in the constant string, or your program will crash Can change the pointer value char *pointer = “constant array”; pointer[0] = ‘Z’; //Segmentation fault pointer = array; //This is OK
Should copy each character to new string Will create two different strings Should not simply assign a new address Will have two pointers pointing to the same string