Skip to content

Instantly share code, notes, and snippets.

@bond15
Last active May 18, 2021 15:41
Show Gist options
  • Save bond15/b07cabd034069964a37dcea57c9cb3f9 to your computer and use it in GitHub Desktop.
Save bond15/b07cabd034069964a37dcea57c9cb3f9 to your computer and use it in GitHub Desktop.
pointers
#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