Last active
February 17, 2020 03:17
-
-
Save keegoo/6349c5aab2672b0a2d2d54838d79a5e9 to your computer and use it in GitHub Desktop.
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
// --------------- catalog --------------- | |
// | |
// * basic data type and size(64-bit platforms) | |
// * padding for alignment requirements | |
// * a useful function to print number in binary | |
// * pointer and double pointer | |
// * printf | |
// * struct | |
// * initialize and access | |
// * access through pointer | |
// * nested struct and access | |
// * stack vs heap | |
// * function pointer & callback function | |
// * typedef function pointer | |
// * initialize and iterate linked nodes | |
// ########## ########## ########## ########## | |
// ## basic data type and size(64-bit platforms) | |
#include <stdio.h> | |
int main() | |
{ | |
// char: 1 byte | |
printf("char: %d bytes\n", sizeof(char)); | |
printf("unsigned char: %d bytes\n", sizeof(unsigned char)); | |
printf("signed char: %d bytes\n", sizeof(signed char)); | |
// int: 4 bytes | |
printf("int: %d bytes\n", sizeof(int)); | |
printf("unsigned int: %d bytes\n", sizeof(unsigned int)); | |
// short: 2 bytes | |
printf("short: %d bytes\n", sizeof(short)); | |
printf("unsigned short: %d bytes\n", sizeof(unsigned short)); | |
// long: 8 bytes | |
printf("long: %d bytes\n", sizeof(long)); | |
printf("unsigned int: %d bytes\n", sizeof(unsigned long)); | |
// float: 4 bytes | |
printf("float: %d bytes\n", sizeof(float)); | |
// double: 8 bytes | |
printf("double: %d bytes\n", sizeof(double)); | |
// void: 1 byte | |
printf("void: %d byte\n", sizeof(void)); | |
// pointer: all pointers are 8 bytes | |
printf("char*: %d bytes\n", sizeof(char*)); | |
printf("int*: %d bytes\n", sizeof(int*)); | |
printf("short*: %d bytes\n", sizeof(short*)); | |
printf("long*: %d bytes\n", sizeof(long*)); | |
printf("float*: %d bytes\n", sizeof(float*)); | |
printf("double*: %d bytes\n", sizeof(double*)); | |
printf("void*: %d bytes\n", sizeof(void*)); | |
return 0; | |
} | |
// *** padding for alignment requirements | |
// | |
// in my case(depends on your compiler): | |
// when there's single type in struct, no padding. | |
// when there's multiple types in struct, will padding to 8 bytes. | |
struct A { | |
char ch; | |
}; | |
struct B { | |
char ch; | |
int i; | |
}; | |
struct C { | |
char ch[9]; | |
}; | |
struct D { | |
char ch[9]; | |
int i; | |
void* pointer; | |
}; | |
sizeof(struct A); // -> 1 byte | |
sizeof(struct B); // -> 8 bytes, as `1 + 4 < 8` then padding to 8 bytes | |
sizeof(struct C); // -> 9 bytes | |
sizeof(struct D); // -> 24 bytes, as `9 + 4 + 8 < 24` then padding to 24 bytes | |
// the variables defined by struct A, B, C or D has the same size as their type. | |
struct A a; sizeof(a); // -> 1 byte | |
struct B b; sizeof(b); // -> 8 bytes | |
struct C c; sizeof(c); // -> 9 bytes | |
struct D d; sizeof(d); // -> 24 bytes | |
// *** a useful function to print number in binary | |
#include <stdio.h> | |
void print_bits(size_t const size, void const * const ptr) | |
{ | |
unsigned char *b = (unsigned char*) ptr; | |
unsigned char byte; | |
int i, j; | |
for (i = size - 1; i >= 0; i--) | |
{ | |
for (j = 7; j >= 0; j--) | |
{ | |
byte = (b[i] >> j) & 1; | |
printf("%u", byte); | |
} | |
} | |
printf("\n"); | |
} | |
int main(int argv, char* argc[]) | |
{ | |
int i = 23; | |
float f = 23.45f; | |
long z = 3456; | |
print_bits(sizeof(i), &i); // 00000000000000000000000000010111 | |
print_bits(sizeof(f), &f); // 01000001101110111001100110011010 | |
print_bits(sizeof(z), &z); // 0000000000000000000000000000000000000000000000000000110110000000 | |
return 0; | |
} | |
// ########## ########## ########## ########## | |
// ## pointer and double pointer | |
#include <stdio.h> | |
int main() | |
{ | |
int num = 123; | |
int* pr2; | |
int** pr1; | |
pr2 = # | |
pr1 = &pr2; | |
/* Possible ways to find value of variable num*/ | |
printf("Value of num is: %d\n", num); | |
printf("Value of num using pr2 is: %d\n", *pr2); | |
printf("Value of num using pr1 is: %d\n", **pr1); | |
/*Possible ways to find address of num*/ | |
printf("Address of num is: %p\n", &num); | |
printf("Address of num using pr2 is: %p\n", pr2); | |
printf("Address of num using pr1 is: %p\n", *pr1); | |
/*Find value of pointer*/ | |
printf("Value of Pointer pr2 is: %p\n", pr2); | |
printf("Value of Pointer pr2 using pr1 is: %p\n", *pr1); | |
/*Ways to find address of pointer*/ | |
printf("Address of Pointer pr2 is: %p\n", &pr2); | |
printf("Address of Pointer pr2 using pr1 is: %p\n", pr1); | |
/*Double pointer value and address*/ | |
printf("Value of Pointer pr1 is: %p\n", pr1); | |
printf("Address of Pointer pr1 is: %p\n", &pr1); | |
/* true */ | |
num == *pr2; *pr2 == **pr1; | |
&num == pr2; pr2 == *pr1; | |
&pr2 == pr1; | |
return 0; | |
} | |
// ########## ########## ########## ########## | |
// printf | |
int i = 0; | |
float f = 0.1; | |
double d = 0.2; | |
printf("int %d\n", i); | |
printf("float %f\n", f); | |
printf("double %f\n", d); | |
printf("address %p\n", &i); | |
// ########## ########## ########## ########## | |
// ## struct | |
// *** initialize and access | |
#include <stdio.h> | |
struct Books { | |
char title[50]; | |
char author[50]; | |
int id; | |
}; | |
int main() { | |
struct Books b1 = {"C Programming", "Nuha Ali", 123456}; | |
printf("Book 1 title : %s\n", b1.title); | |
printf("Book author : %s\n", b1.author); | |
printf("Book 1 id: %d\n", b1.id); | |
return(0); | |
} | |
// *** access through pointer | |
void print_book(struct Books *book) { | |
printf("Book title : %s\n", book->title); | |
printf("Book author : %s\n", book->author); | |
printf("Book id : %d\n", book->id); | |
} | |
int main() { | |
struct Books b1 = {"C Programming", "Nuha Ali", 123456}; | |
print_book(&b1); | |
return(0); | |
} | |
// *** nested struct and access | |
#include <stdio.h> | |
struct Author { | |
char first[50]; | |
char last[50]; | |
}; | |
struct Books { | |
char title[50]; | |
struct Author author; | |
int id; | |
}; | |
void print_book(struct Books *book) { | |
printf("Book title : %s\n", book->title); | |
printf("Book author : %s\n", book->author.first); | |
printf("Book id : %d\n", book->id); | |
} | |
int main() { | |
struct Books b1 = {"C Programming", {"Nuha", "Ali"}, 123456}; | |
printf("Book 1 title : %s\n", b1.title); | |
printf("Book author : %s\n", b1.author.first); | |
printf("Book 1 id: %d\n", b1.id); | |
print_book(&b1); | |
return(0); | |
} | |
// ########## ########## ########## ########## | |
// ## stack vs heap | |
// *** stack | |
#include <stdio.h> | |
double multiplyByTwo (double input) { | |
double twice = input * 2.0; | |
return twice; | |
} | |
int main (int argc, char *argv[]) | |
{ | |
int age = 30; | |
double salary = 12345.67; | |
double myList[3] = {1.2, 2.3, 3.4}; | |
printf("double your salary is %.3f\n", multiplyByTwo(salary)); | |
return 0; | |
} | |
// *** heap | |
#include <stdio.h> | |
#include <stdlib.h> | |
double *multiplyByTwo (double *input) { | |
double *twice = malloc(sizeof(double)); | |
*twice = *input * 2.0; | |
return twice; | |
} | |
int main (int argc, char *argv[]) | |
{ | |
int *age = malloc(sizeof(int)); | |
*age = 30; | |
double *salary = malloc(sizeof(double)); | |
*salary = 12345.67; | |
double *myList = malloc(3 * sizeof(double)); | |
myList[0] = 1.2; | |
myList[1] = 2.3; | |
myList[2] = 3.4; | |
double *twiceSalary = multiplyByTwo(salary); | |
printf("double your salary is %.3f\n", *twiceSalary); | |
free(age); | |
free(salary); | |
free(myList); | |
free(twiceSalary); | |
return 0; | |
} | |
// ########## ########## ########## ########## | |
// ## function pointer & callback function | |
// *** function pointer | |
#include <stdio.h> | |
void fun(int a) { printf("Value of a is %d\n", a); } | |
int main() | |
{ | |
// fun_ptr is a pointer to function fun() | |
void (*fun_ptr)(int) = &fun; | |
// Invoking fun() using fun_ptr | |
(*fun_ptr)(10); | |
return 0; | |
} | |
// *** callbacks | |
#include <stdio.h> | |
void fun1(int a) {printf("fun1 and %d\n", a);} | |
void fun2(int a) {printf("fun2 and %d\n", a);} | |
void wrapper(void (*fun)(int)) | |
{ | |
fun(10); | |
} | |
int main() | |
{ | |
wrapper(fun1); | |
wrapper(fun2); | |
return 0; | |
} | |
// ########## ########## ########## ########## | |
// ## typedef function pointer | |
// compare with previous example | |
#include <stdio.h> | |
void fun1(int a) {printf("fun1 and %d\n", a);} | |
void fun2(int a) {printf("fun2 and %d\n", a);} | |
// define the new pattern `void identifier(int)` as a type `for_fun` | |
typedef void (*for_fun)(int); | |
void wrapper(for_fun fun) | |
{ | |
fun(10); | |
} | |
int main() | |
{ | |
wrapper(fun1); | |
wrapper(fun2); | |
return 0; | |
} | |
// ########## ########## ########## ########## | |
// ## initialize and iterate linked nodes | |
#include <stdio.h> | |
#include <stdlib.h> | |
typedef struct Node* NodePtr; | |
struct Node { | |
struct Node* next; | |
int id; | |
}; | |
NodePtr append(NodePtr n) { | |
NodePtr res = malloc(sizeof(*res)); | |
res->next = n; | |
res->id = rand(); | |
return res; | |
} | |
int main() { | |
// initialize head | |
NodePtr head = malloc(sizeof(*head)); | |
head->next = NULL; | |
head->id = 0; | |
// chain Nodes with append() | |
int i; | |
for(i = 0; i < 10; i ++) | |
head = append(head); | |
// iterate and print | |
NodePtr current = head; | |
while(1) { | |
printf("%d\n", current->id); | |
current = current->next; | |
if(current == NULL) { break; } | |
} | |
return(0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment