Last active
May 18, 2021 15:41
-
-
Save bond15/b07cabd034069964a37dcea57c9cb3f9 to your computer and use it in GitHub Desktop.
pointers
This file contains hidden or 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
#import "stdio.h" | |
typedef struct foo { | |
int data; | |
} foo; | |
typedef struct bar{ | |
int bla; | |
char letter; | |
}bar; | |
void print_bits ( void* buf, size_t size_in_bytes ) | |
{ | |
char* ptr = (char*)buf; | |
for (size_t i = 0; i < size_in_bytes; i++) { | |
for (short j = 0; j <8 ; j++) { | |
printf("%d", (ptr[i] >> j) & 1); | |
} | |
printf(" "); | |
} | |
printf("\n"); | |
} | |
int main() { | |
// the function `sizeof` tells the size of a type in bytes | |
// the size of a char is 1 byte | |
printf("%d\n",sizeof(char)); | |
// the size of an int is 4 bytes | |
printf("%d\n",sizeof(int)); | |
// the size of a struct ("object") of type `foo` is 4 bytes | |
// this makes sense since `foo` only contains an integer which requires 4 bytes to store | |
printf("%d\n",sizeof(foo)); | |
// the size of a struct ("object") of type 'bar' is 8 bytes | |
// this makes sense since 'bar' has an integer and a char | |
// integer requires 4 bytes, char requires 1 byte | |
// but here it rounds up to 8 bytes to store both. | |
printf("%d\n", sizeof(bar)); | |
// allocate data of each type | |
char x = 'a'; | |
int y = 7; | |
foo f; | |
f.data = 8; | |
bar b; | |
b.bla = 9; | |
b.letter = 'b'; | |
print_bits(&x,sizeof(char)); | |
// so lets observe what is actually in memory | |
//NOTE: THE LEAST SIGNIFICANT BIT IS PRINTED AS THE LEFTMOST BIT | |
// print_bits takes an address and prints `n` bits starting from that address | |
print_bits(&x,sizeof(char)); | |
// this statement yields: 10000110 (LEAST SIGNIFICANT BIT ON LEFT) | |
// which is 1 byte or 8 bits at address x | |
// but we stored the letter 'a' at that address... | |
// well 01100001 is binary for the number '97' | |
// and letters/char are encoded in ASCII where 'a' = 97! | |
// so what about 'y' where we stored the integer 7? | |
print_bits(&y,sizeof(int)); | |
// 11100000 00000000 00000000 00000000 | |
// we see that there are 4 bytes and the 1st byte contains the number 7! | |
//cool! how about structures? | |
print_bits(&f,sizeof(foo)); | |
// 00010000 00000000 00000000 00000000 | |
// this is a struct but it only contains an int which is 4 bytes | |
// note that the first byte contains the value 8! | |
print_bits(&b,sizeof(bar)); | |
/* 10010000 00000000 00000000 00000000 01000110 00000000 00000000 00000000 | |
so bar is a struct type | |
typedef struct bar{ | |
int bla; | |
char letter; | |
}bar; | |
We see that the first 4 bytes are | |
10010000 00000000 00000000 00000000 | |
which is the integer 9 that we stored | |
and the second 4 bytes are | |
01000110 00000000 00000000 00000000 | |
which is the char 'b' in the first byte | |
*/ | |
// updating structs | |
/* when we update a struct.. what are we doing? | |
well lets look at the addresses first | |
*/ | |
// printing the address of b which is an instance of the 'bar' struct | |
// as a number | |
printf("%uL\n",&b); | |
/* | |
3804662520 | |
^ this is the ADDRESS of where `b` is stored, interpreted as a number! | |
(Think of memory as just one BIG array :) ) | |
NOTE: THIS VALUE IS NONDETERMINISTIC w.r.t. each run to a program. | |
(programs will run in different parts of memory each time they are executed) | |
now watch this */ | |
// we can print the address of the 'letter' field in b | |
printf("%uL\n", &(b.letter)); | |
/* | |
3804662524 | |
This is the ADDRESS of where 'b'.letter is stored! interpreted as a number | |
Notice that 3804662524 - 3804662520 is 4 | |
recall the printed value of b | |
(10010000 00000000 00000000 00000000) (01000110 00000000 00000000 00000000) | |
^ 3804662520 ^ 3804662524 | |
memory is just a "big array" so we are just indexing into it and changing a value! | |
*/ | |
// sooo updating 'b.letter' | |
b.letter = 'z'; | |
// is equivalent to | |
// interpreting address of 'b' as an char pointer | |
char * p = (char *) &b; | |
/* | |
10010000 00000000 00000000 00000000 01000110 00000000 00000000 00000000 | |
^ p | |
(where p is type 'char *') | |
*/ | |
p += 4; | |
/* | |
and increment the pointer by 4 bytes | |
10010000 00000000 00000000 00000000 01000110 00000000 00000000 00000000 | |
^ p | |
*/ | |
*p = 'z'; | |
/* | |
and modifying the value there to 'z' in ASCII 122 or 01111010 (01011110 BUT WE FLIP ORDER) | |
10010000 00000000 00000000 00000000 01011110 00000000 00000000 00000000 | |
^ p | |
*/ | |
printf("%c\n",b.letter); | |
print_bits(&b,sizeof(bar)); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment