-
-
Save najashark/b00c576684053db874aad61f581bd7c2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
https://www.andrew.cmu.edu/user/mteh/docs/C_Pointers.txt | |
Pointers | |
===================================================================== | |
--------------------------------------------------------------------- | |
Reading C type declarations | |
--------------------------------------------------------------------- | |
void * foo; (foo is a pointer to void; generic pointer) | |
char * foo; (foo is a pointer to char) | |
long **foo[7]; (foo is an array of 7 pointer to pointer to long) | |
1. start with var name (e.g. foo is ... ) | |
2. end with basic type (e.g. foo is ... int) | |
3. filling in: ``go right when you can, go left when you must'' | |
defs: | |
* means ``pointer to'' | |
[] means ``array of'' | |
() means ``function returning'' | |
ref: http://unixwiz.net/techtips/reading-cdecl.html | |
Example from K&R: | |
int (*comp)(void *, void *); | |
// comp is a pointer to a funct (that has two void * arguments) returning int | |
int *comp(void *, void *); | |
// comp is a funct (that has two void * arguments) returning a pointer to int | |
===================================================================== | |
--------------------------------------------------------------------- | |
Example (from K&R): | |
--------------------------------------------------------------------- | |
int *p; // p is a pointer to int | |
int *x; | |
p = &c; // p stores the address of c | |
// p is said to ``point to'' c | |
p = c; // p stores the address `c' | |
// p points to whatever is at the address `c' | |
p = *x; // p stores the address ``int, which x points to''. | |
* is the _indirection_ or _dereferencing_ _operator_ | |
when applied to a pointer, it accesses the obj the pointer points to. | |
&x produces the mem address where x is stored. | |
& is the address-of operator | |
int x = 1, y = 2, z[10]; | |
int *p; // p is pointer to int | |
p = &x; // p now points to x | |
y = *p; // retrieves value of `int x' which is 1. Hence, y is now 1. | |
*p = 0; // assign 0 to the object that p pointers to. Hence, x is now 0. | |
p = &z[0]; // p now points to z[0] | |
p = z; // p now points to z[0] | |
p = &z; //invalid since `z' is an array | |
strcpy(dest, source) always slap a terminating null char (ascii 0) to the str. | |
// length is _determined_ by terminating null char; | |
// strlen excludes the null terminating char | |
hence, dest = malloc(strlen(source) + 1); | |
sizeof(void) // is _illegal_ | |
int dict[5][4]; | |
dict[2][3] = 7; | |
printf("%d\n", *(*(dict + 2)+3) ); // outputs 7 | |
*(*(dict+i)+3) == dict[i][3]; | |
// &i = 2000 | |
int *next_int = &i + 1; //next_int => 2004 (int is 4 byte); (char is 1 byte) | |
char **dict = 3000; | |
dict+1 => 3004 // pointer is 4 byte | |
sizeof(node->word); // sizeof gives 4. word is a pointer | |
char static_word[10]; | |
sizeof(static_word) => 10; //alr defined above | |
char *static_word[10]; | |
sizeof(static_word) = 40 // pointer is 4 byte x 10 -> 40 | |
===================================================================== | |
--------------------------------------------------------------------- | |
Postfix Operators (binds more tightly): ++, --, [] | |
--------------------------------------------------------------------- | |
int array[] = {45,67,89}; | |
int *ptr = array; // same as: int *ptr; ptr = array; | |
*(ptr++) is the same as *ptr++ (both returns 45) | |
array[0]; (return 45; but the [] in array[0] has _nothing_to_do_ with arrays) | |
array[1]; (return 67, same as *(array+1);) | |
int *p = &array[1]; // p is a pointer to array[1] (aka the obj `67'). | |
// &array[1] is equiv (array+1); | |
p[1]; // gives 89. why? | |
// same as *(p+1) eq *(&array[1] + 1) eq *(array+1 + 1) eq *(array + 2); | |
int arr[3] = {12,23,34}; | |
int *ptr = arr; | |
*ptr++; is equiv to *(ptr++); // res: 12 | |
*++ptr; is equiv to *(++ptr); // res: 23 | |
++*ptr; is equiv to ++(*ptr); // res: 23+1 = 24 | |
++*++ptr; is equiv to ++(*(++ptr)); // res: 23+1 = 24 | |
++*ptr++; is equiv to ++(*(ptr++)); // res: 12+1 = 13 | |
void foo(int arr[]); is equiv to: void foo(int *arr); | |
int arr[]; // illegal byitself. need: int arr[10]; or: int arr[] = {1}; | |
int *arr; //legal | |
char *word = "HelloWorld"; // a pointer; to a string _constant_ | |
// if try to modify: segfault, or unpredictable behaviour | |
char word[] = "HelloWorld"; // an array, includes '\0' | |
Multiple Indirection | |
int a = 3; | |
int *b = &a; | |
int **c = &b; | |
int ***d = &c; | |
*d == c; Dereferencing an (int ***) once gets you an (int **) (3 - 1 = 2) | |
**d == *c == b; Dereferencing an (int ***) twice, or an (int **) once, | |
gets you an (int *) (3 - 2 = 1; 2 - 1 = 1) | |
***d == **c == *b == a == 3; | |
Dereferencing an (int ***) thrice, or an (int **) twice, or an (int *) once, | |
gets you an int (3 - 3 = 0; 2 - 2 = 0; 1 - 1 = 0) | |
=============================================================================== | |
------------------------------------------------------------------------------- | |
Structures | |
------------------------------------------------------------------------------- | |
struct point{ | |
int x; int y; | |
}; (note the ";" here) | |
In a method, we can also write: | |
struct {int x; int y;} somepoint; | |
struct rect{ | |
struct point pt1, pt2; // note how we ``combine'' into one line | |
}; | |
if p is a pointer to a structure, | |
then p->member-of-structure referes to the particular member | |
'->' is short-hand for (*p).member | |
Note that . and -> associate from left to right | |
struct rect r, *rp = &r; | |
these four exprs are equiv: | |
r.pt1.x | |
rp->pt1.x | |
(r.pt1).x // cannot wrote (r.pt1)->x since r.pt1 is not a pointer | |
(rp->pt1).x | |
Node **node; | |
(*node)->next is NOT equiv to: *node->next; | |
the second one fetches whatever `next' points to, i.e. *(node->next) | |
typedef struct stu{ | |
char *id; | |
}Student; | |
We can write: | |
typedef struct{ | |
char *id; | |
}Student; | |
We can also write: | |
struct Foo{ int dat; }; | |
typedef struct Foo Foo; | |
Student *student; Student s; | |
sizeof(Student) == sizeof(*student) == sizeof(struct stu) == sizeof(s); | |
sizeof is an operator | |
Consider: | |
Student *student = malloc(5*sizeof(Student)); | |
students[1].x is valid | |
students[1]->student is invalid because student[1] is not a pointer | |
(*(students+1)).x is valid | |
=============================================================================== | |
------------------------------------------------------------------------------- | |
Etc | |
------------------------------------------------------------------------------- | |
Consider: | |
int *p; | |
*p = 'a'; | |
what happens? | |
ans: segfault. no memory is allocated for the dereferencing operation |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment