├── Working with Larger Programs ├── Makefiles │ └── MAKEFILE ├── Overview │ ├── other.c │ ├── other.h │ └── main.c ├── Compiling multiple source files from the command line │ ├── other.c │ ├── other.h │ ├── main.c │ ├── 2021-11-05_11-38-24.png │ └── 2021-11-05_11-39-33.png └── Heap and stack memory allocation │ ├── working_with_the_stack_memory.c │ └── working_with_the_heap_memory.c ├── Advanced Control Flow ├── The null statement │ └── The null statement └── The goto statement │ └── using_the_goto_statement.c ├── The Preprocessor ├── Include guards and undef directive │ ├── using_include_guards.c │ ├── using_undef.c │ ├── using_undef.h │ └── using_include_guards.h └── Conditional Compilation │ ├── using_ifdef.c │ ├── using_ifdef_else.c │ ├── if_else_preprocessir_directive.c │ └── using_ifdef_undefine_macro.c ├── Shared Libraries and Shared Objects ├── Creating a static library │ ├── myStaticLibrary │ │ ├── myStaticLibrary │ │ ├── main.c │ │ ├── myStaticLibrary.h │ │ ├── obj │ │ │ └── Debug │ │ │ │ └── main.o │ │ ├── bin │ │ │ └── Debug │ │ │ │ └── libmyStaticLibrary.a │ │ ├── myStaticLibrary.layout │ │ └── myStaticLibrary.cbp │ └── myDemo │ │ ├── main.c │ │ ├── bin │ │ └── Debug │ │ │ └── myDemo │ │ ├── obj │ │ └── Debug │ │ │ └── main.o │ │ ├── myDemo.layout │ │ └── myDemo.cbp └── Creating a dynamic library │ ├── myLib │ ├── myDynamicLib.h │ └── myDynamicLib.c │ └── DemoDynamicLibrary │ └── main.c ├── 2021-11-04_16-18-29.png ├── Interprocess Communication ├── get_process_id ├── The fork sistem call │ └── basic_example_of_fork.c ├── raising_an_alarm_signal.c ├── raising_a_signal.c ├── get_process_id.c ├── Handling a signal using the signal function │ └── using_the_signal_function.c ├── listing_the_signals_from_command_line.txt └── testing_continuing_after_raising_sigstop_from_command_line.txt ├── Working with extern variables ├── file.c ├── otherfile.c ├── otherfile.h ├── types.h ├── file.h └── main.c ├── Type Qualifiers └── using_the_const_type_qualifier.c ├── Macros ├── Creating your own macros │ ├── creating_a_macro_from_another_macro.c │ ├── create_macro_with_ternary_condition_operator.c │ ├── create_macro_for_non_standard_C_code.c │ └── creating_your_own.macros.c ├── Overview │ ├── main.c │ └── main.h ├── Preprocessor Operators │ ├── using_the_backslash_operator.c │ ├── using_the_defined_operator.c │ ├── using_the_pound_operator_string_expansion.c │ └── using_the_pound_pound_concatenation_operator.c └── Predefined Macros │ └── using_predefined_macros.c ├── Storage classes ├── External variables │ ├── Using extern with functions │ │ ├── other_file.c │ │ └── using_extern_with_functions.c │ └── Using extern with global variables │ │ ├── other_version_2.c │ │ ├── other.c │ │ ├── external_variables.c │ │ └── external_variables_second_version_of_definition.c ├── Static variables │ ├── Using static functions │ │ ├── supplementary.c │ │ └── using_static_functions.c │ └── Using static variables in functions │ │ └── using_static_variables.c ├── Automatic variables │ └── automatic_storage_classes.c └── Register variables │ └── using_the_register_storage_class.c ├── Advanced Debugging and Analysis ├── Using core-dump files │ ├── a_program_that_returns_segfault_example_2.c │ ├── a_program_that_returns_segfault_example_3.c │ ├── a_program_that_returns_segfault_example_4.c │ └── a_program_that_returns_segfault_example_1.c ├── Debugging with the GNU Project Debugger gdb │ ├── debug_with_gdb.c │ └── debug_with_gdb_struct_and_pointers.c └── use_preprocessor_to_debug.c ├── Input and Output ├── Functions dealing with strings │ ├── using_puts.c │ ├── using_fputs.c │ ├── using_fgets.c │ ├── using_getline_example_with_character_array.c │ └── using_getline_example_1.c ├── Functions dealing with characters │ ├── use_getc_to_read_from_terminal.c │ ├── Output functions │ │ ├── use_putchar_another_example.c │ │ ├── use_putc_with_stdout.c │ │ ├── use_fputc_with_a_file.c │ │ ├── use_putchar.c │ │ ├── use_putc_with_a_file.c │ │ └── thefile.txt │ ├── use_getc_to_read_from_file.c │ ├── thefile.txt │ ├── use_getchar_to_read_from_terminal.c │ ├── use_fgetc_to_read_from_file.c │ └── use_ungetc_to_put_back_character_to_the_stream.c └── Formatting functions │ ├── using_fprintf_and_stderr.c │ ├── using_fscanf.c │ ├── using_sprintf.c │ ├── using_sscanf.c │ └── using_fprintf.c ├── Advanced Data Types ├── using_typedef.c ├── Variable length arrays │ ├── variable_length_array_example_1.c │ ├── variable_length_array_example_2.c │ ├── variable_length_array_example_multiple_dimensions.c │ └── challenge.c ├── Designated Initializers │ ├── example_using_designated_initializers_with_arrays.c │ ├── example_using_designated_initializers_with_an_array_of_structures.c │ └── example_using_designated_initializers_with_structures.c ├── the_define_preprocessor_directive.c └── Flexible array members │ ├── challenge.c │ └── example_using_flexible_array_members.c ├── Unions ├── Accessing a union │ ├── initializing_the_members_of_a_union_example.c │ ├── accessing_the_members_of_a_union_example_2.c │ └── accessing_the_members_of_a_union_example_1.c ├── challenge.c └── Defining a union │ └── example_how_to_define_a_union.c ├── Useful C libraries └── Assert │ ├── an_example_of_using_assert_1.c │ ├── switch_off_assertions.c │ └── an_example_of_using_assert_2.c ├── README.md ├── Bit manipulations ├── Bitwise Operators │ ├── Logical_binary_operators_AND.c │ ├── Logical_binary_operators_OR.c │ ├── Logical_binary_operators_XOR.c │ └── Logical_binary_operators_binary_complement.c └── Binary numbers and bits │ ├── challenge_convert__decimal_numbers_to_binary_numbers.c │ └── challenge_convert_binary_numbers_to_decimal.c ├── Advanced Pointers ├── Void pointers │ ├── pointer_arithmetic_with_void_pointers.c │ ├── size_of_void_pointers.c │ └── using_void_pointer_example1.c ├── Use Cases │ ├── 2nd_use_case_of_using_double_pointers_case_CRASH.c │ ├── 2nd_use_case_of_using_double_pointers_case_RESOLVED.c │ ├── use_double_pointer_to_pass_pointer_by_reference_in_function.c │ ├── example_when_passing_function_argument_pointer_as_copy_2.c │ └── example_when_passing_function_argument_pointer_as_copy.c ├── Functions Pointers │ ├── example_of_using_function_pointers_1.c │ ├── example_of_using_function_pointers_2.c │ └── example_of_using_function_pointers_3.c ├── example.c ├── conceptual_pointer_to_pointer.c ├── conceptual_example_2_pointer_to_pointer.c └── conceptual_example_3_pointer_to_pointer.c ├── Threads ├── Creating a thread │ └── create_a_thread.c ├── Common Thread Functions │ ├── using_pthread_cancel.c │ ├── using_pthread_self_function.c │ ├── using_pthread_detach.c │ └── stack_management_functions.c ├── Passing arguments and returning values │ ├── returning_values_from_threads.c │ ├── passing_a_single_argument_to_a_thread.c │ └── passing_an_argument_as_a_struct.c └── Thread Synchronisation Concepts │ ├── using_mutex_example_2.c │ ├── using_mutex_example_1.c │ ├── an_example_of_deadlock.c │ └── solution_to_resolve_a_deadlock.c ├── Networking ├── creating_a_client_socket.c └── creating_a_server_socket.c └── Data Structures └── Linked Lists └── main.c /Working with Larger Programs/Makefiles/MAKEFILE: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Advanced Control Flow/The null statement/The null statement: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /The Preprocessor/Include guards and undef directive/using_include_guards.c: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Shared Libraries and Shared Objects/Creating a static library/myStaticLibrary/myStaticLibrary: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /2021-11-04_16-18-29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgecatalin/Advanced-C-Programming-Course/HEAD/2021-11-04_16-18-29.png -------------------------------------------------------------------------------- /Working with Larger Programs/Overview/other.c: -------------------------------------------------------------------------------- 1 | #include "other.h" 2 | 3 | int getfavouritenumber() 4 | { 5 | return 13; 6 | } 7 | -------------------------------------------------------------------------------- /Interprocess Communication/get_process_id: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgecatalin/Advanced-C-Programming-Course/HEAD/Interprocess Communication/get_process_id -------------------------------------------------------------------------------- /The Preprocessor/Include guards and undef directive/using_undef.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | int main(void) 5 | { 6 | 7 | 8 | 9 | return 0; 10 | } -------------------------------------------------------------------------------- /Working with Larger Programs/Compiling multiple source files from the command line/other.c: -------------------------------------------------------------------------------- 1 | #include "other.h" 2 | 3 | int getfavouritenumber() 4 | { 5 | return 13; 6 | } 7 | -------------------------------------------------------------------------------- /Working with Larger Programs/Overview/other.h: -------------------------------------------------------------------------------- 1 | #ifndef OTHER_H_INCLUDED 2 | #define OTHER_H_INCLUDED 3 | 4 | int getfavouritenumber(); 5 | 6 | #endif // OTHER_H_INCLUDED 7 | -------------------------------------------------------------------------------- /The Preprocessor/Include guards and undef directive/using_undef.h: -------------------------------------------------------------------------------- 1 | #ifndef _USING_UNDEF_H 2 | #define _USING_UNDEF_H 3 | 4 | #define UNIX 5 | #undef UNIX 6 | 7 | 8 | #endif -------------------------------------------------------------------------------- /Working with Larger Programs/Overview/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "other.h" 3 | 4 | int main(void) 5 | { 6 | printf("%d",getfavouritenumber()); 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /Shared Libraries and Shared Objects/Creating a dynamic library/myLib/myDynamicLib.h: -------------------------------------------------------------------------------- 1 | #ifndef MYDYAMICLIB_H_INCLUDED 2 | #define MYDYAMICLIB_H_INCLUDED 3 | 4 | void myFunction(void); 5 | 6 | #endif -------------------------------------------------------------------------------- /Working with extern variables/file.c: -------------------------------------------------------------------------------- 1 | #include "file.h" 2 | 3 | void wow() 4 | { 5 | dacia.speed=500; 6 | printf("the elements are %d ; %d ; %s .\n", dacia.speed,dacia.power, dacia.color); 7 | } 8 | -------------------------------------------------------------------------------- /Shared Libraries and Shared Objects/Creating a dynamic library/DemoDynamicLibrary/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main (void) 5 | { 6 | myFunction(); 7 | return 0; 8 | } -------------------------------------------------------------------------------- /Shared Libraries and Shared Objects/Creating a dynamic library/myLib/myDynamicLib.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void myFunction(void) 4 | { 5 | printf("Hello from executing myFunction() in the dynamic library.\n"); 6 | } -------------------------------------------------------------------------------- /Working with Larger Programs/Compiling multiple source files from the command line/other.h: -------------------------------------------------------------------------------- 1 | #ifndef OTHER_H_INCLUDED 2 | #define OTHER_H_INCLUDED 3 | 4 | int getfavouritenumber(); 5 | 6 | #endif // OTHER_H_INCLUDED 7 | -------------------------------------------------------------------------------- /Shared Libraries and Shared Objects/Creating a static library/myStaticLibrary/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void myFunction(void) 4 | { 5 | printf("This is myFunction() executed from the static library.\n"); 6 | } 7 | -------------------------------------------------------------------------------- /Type Qualifiers/using_the_const_type_qualifier.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) 4 | { 5 | const double pi=3.1415f; 6 | 7 | const int myArray[3]={2,22,33}; 8 | 9 | 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /Working with Larger Programs/Compiling multiple source files from the command line/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "other.h" 3 | 4 | int main(void) 5 | { 6 | printf("%d",getfavouritenumber()); 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /Working with extern variables/otherfile.c: -------------------------------------------------------------------------------- 1 | #include "otherfile.h" 2 | 3 | 4 | void printsome() 5 | { 6 | dacia.speed=dacia.speed*10; 7 | printf("the elements are %d ; %d ; %s .\n", dacia.speed,dacia.power, dacia.color); 8 | } 9 | -------------------------------------------------------------------------------- /Working with extern variables/otherfile.h: -------------------------------------------------------------------------------- 1 | #ifndef OTHERFILE_H_INCLUDED 2 | #define OTHERFILE_H_INCLUDED 3 | 4 | #include "types.h" 5 | extern thiscar dacia; 6 | 7 | void printsome(); 8 | 9 | #endif // OTHERFILE_H_INCLUDED 10 | -------------------------------------------------------------------------------- /Shared Libraries and Shared Objects/Creating a static library/myDemo/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "myStaticLibrary.h" 5 | 6 | int main() 7 | { 8 | myFunction(); 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /Macros/Creating your own macros/creating_a_macro_from_another_macro.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define FOO (BAR) 4 | #define BAR ("This is interesting") 5 | 6 | int main(void) 7 | { 8 | printf("%s.\n",BAR); 9 | return 0; 10 | } -------------------------------------------------------------------------------- /Storage classes/External variables/Using extern with functions/other_file.c: -------------------------------------------------------------------------------- 1 | extern int myGlobalVariable; 2 | 3 | extern void displayFunction() 4 | { 5 | printf("This is the variable you are looking for %d.\n",++myGlobalVariable); 6 | } 7 | -------------------------------------------------------------------------------- /Advanced Debugging and Analysis/Using core-dump files/a_program_that_returns_segfault_example_2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) 4 | { 5 | int myArray[]={1953,1954,1978}; 6 | 7 | myArray[3]=2021; 8 | 9 | return 0; 10 | } -------------------------------------------------------------------------------- /Shared Libraries and Shared Objects/Creating a static library/myDemo/bin/Debug/myDemo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgecatalin/Advanced-C-Programming-Course/HEAD/Shared Libraries and Shared Objects/Creating a static library/myDemo/bin/Debug/myDemo -------------------------------------------------------------------------------- /Shared Libraries and Shared Objects/Creating a static library/myDemo/obj/Debug/main.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgecatalin/Advanced-C-Programming-Course/HEAD/Shared Libraries and Shared Objects/Creating a static library/myDemo/obj/Debug/main.o -------------------------------------------------------------------------------- /Working with extern variables/types.h: -------------------------------------------------------------------------------- 1 | #ifndef TYPES_H_INCLUDED 2 | #define TYPES_H_INCLUDED 3 | 4 | typedef struct car 5 | { 6 | int power; 7 | int speed; 8 | char color[30]; 9 | } thiscar; 10 | 11 | #endif // TYPES_H_INCLUDED 12 | -------------------------------------------------------------------------------- /Shared Libraries and Shared Objects/Creating a static library/myStaticLibrary/myStaticLibrary.h: -------------------------------------------------------------------------------- 1 | #ifndef MYSTATICLIBRARY_H_INCLUDED 2 | #define MYSTATICLIBRARY_H_INCLUDED 3 | 4 | void myFunction(void); 5 | 6 | 7 | 8 | #endif // MYSTATICLIBRARY_H_INCLUDED 9 | -------------------------------------------------------------------------------- /Shared Libraries and Shared Objects/Creating a static library/myStaticLibrary/obj/Debug/main.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgecatalin/Advanced-C-Programming-Course/HEAD/Shared Libraries and Shared Objects/Creating a static library/myStaticLibrary/obj/Debug/main.o -------------------------------------------------------------------------------- /Storage classes/Static variables/Using static functions/supplementary.c: -------------------------------------------------------------------------------- 1 | 2 | void foo() 3 | { 4 | puts("This is from inside the foo() function."); 5 | } 6 | 7 | static void bar() 8 | { 9 | puts("This is from inside the bar() function."); 10 | } 11 | -------------------------------------------------------------------------------- /Input and Output/Functions dealing with strings/using_puts.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(void) 6 | { 7 | char myString[40]; 8 | strcpy(myString,"Salaam alaykum"); 9 | puts(myString); 10 | 11 | return 0; 12 | } -------------------------------------------------------------------------------- /Storage classes/External variables/Using extern with global variables/other_version_2.c: -------------------------------------------------------------------------------- 1 | void foo_2() 2 | { 3 | extern int myVariable; //if the extern variable is only to be used in a single function, then it can be declared as extern just inside that function 4 | myVariable+=2; 5 | } 6 | -------------------------------------------------------------------------------- /Working with Larger Programs/Compiling multiple source files from the command line/2021-11-05_11-38-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgecatalin/Advanced-C-Programming-Course/HEAD/Working with Larger Programs/Compiling multiple source files from the command line/2021-11-05_11-38-24.png -------------------------------------------------------------------------------- /Working with Larger Programs/Compiling multiple source files from the command line/2021-11-05_11-39-33.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgecatalin/Advanced-C-Programming-Course/HEAD/Working with Larger Programs/Compiling multiple source files from the command line/2021-11-05_11-39-33.png -------------------------------------------------------------------------------- /Working with extern variables/file.h: -------------------------------------------------------------------------------- 1 | #ifndef FILE_H_INCLUDED 2 | #define FILE_H_INCLUDED 3 | 4 | #include 5 | #include 6 | #include 7 | #include "types.h" 8 | 9 | extern thiscar dacia; 10 | 11 | void wow(); 12 | 13 | #endif // FILE_H_INCLUDED 14 | -------------------------------------------------------------------------------- /Shared Libraries and Shared Objects/Creating a static library/myStaticLibrary/bin/Debug/libmyStaticLibrary.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georgecatalin/Advanced-C-Programming-Course/HEAD/Shared Libraries and Shared Objects/Creating a static library/myStaticLibrary/bin/Debug/libmyStaticLibrary.a -------------------------------------------------------------------------------- /Advanced Data Types/using_typedef.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef int Counter; 4 | typedef int * i_pointer; 5 | typedef char* car; 6 | 7 | int main(void) 8 | { 9 | Counter i, j; 10 | i_pointer p; //same as int * p 11 | 12 | 13 | car Dacia, Renault; 14 | 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /Macros/Overview/main.c: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | 3 | 4 | int main(void) 5 | { 6 | int x=43; 7 | int y=10; 8 | 9 | PRNT(x,y); //actually the macro is a text substitution technique and it will be replaced by the content defined for its name in its definition 10 | 11 | return 0; 12 | } -------------------------------------------------------------------------------- /Input and Output/Functions dealing with characters/use_getc_to_read_from_terminal.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) 4 | { 5 | char myChar='\0'; 6 | int myInt=0; 7 | 8 | myChar=getc(stdin); 9 | printf("Hey samurai, you wrote \t %c.\n",myChar); 10 | 11 | 12 | return 0; 13 | } -------------------------------------------------------------------------------- /Macros/Preprocessor Operators/using_the_backslash_operator.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MIN(a,b) \ 4 | ((a)<(b) ? (a) : (b)) 5 | 6 | int main(void) 7 | { 8 | int a=10,b=43; 9 | 10 | printf("The minimum between %d and %d is %d.\n",a,b,MIN(a,b)); 11 | 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /Macros/Preprocessor Operators/using_the_defined_operator.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define THIS_MACRO "Hello" 4 | 5 | #if defined(THIS_MACRO) 6 | #define NEW_MACRO "Cocar" 7 | #endif 8 | 9 | int main(void) 10 | { 11 | printf("%s \t %s .\n",THIS_MACRO,NEW_MACRO); 12 | 13 | return 0; 14 | } -------------------------------------------------------------------------------- /Interprocess Communication/The fork sistem call/basic_example_of_fork.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | int main(void) 8 | { 9 | pid_t p=fork(); 10 | 11 | printf("Hi, There %d\n", p); 12 | 13 | 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /Advanced Data Types/Variable length arrays/variable_length_array_example_1.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) 4 | { 5 | size_t mySize=0; 6 | 7 | printf("Enter the size you wish for the array:\n"); 8 | scanf("%zd",&mySize); 9 | 10 | float myArray[mySize]; 11 | 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /The Preprocessor/Include guards and undef directive/using_include_guards.h: -------------------------------------------------------------------------------- 1 | #ifndef _USING_INCLUDE_GUARDS_H 2 | #define _USING_INCLUDE_GUARDS_H //when other file.h will use #include "using_include_guards.h" it will load this file only once, cause at a subsequent inclusing it is already activated 3 | #include 4 | #endif -------------------------------------------------------------------------------- /Advanced Debugging and Analysis/Using core-dump files/a_program_that_returns_segfault_example_3.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) 4 | { 5 | int numbers_read=0; 6 | int i; 7 | 8 | numbers_read=scanf("%d", i); //error here due to not addressing a valid memory address in scanf 9 | 10 | return 0; 11 | } -------------------------------------------------------------------------------- /Macros/Creating your own macros/create_macro_with_ternary_condition_operator.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAX(a,b) ( (a)>(b) ? (a) : (b)) 4 | 5 | int main(void) 6 | { 7 | int a=43, b=45; 8 | 9 | printf("The maximum between the two arguments is MAX(%d,%d):%d.\n",a,b,MAX(a,b)); 10 | 11 | return 0; 12 | } -------------------------------------------------------------------------------- /Unions/Accessing a union/initializing_the_members_of_a_union_example.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | union example 4 | { 5 | int x; 6 | int y; 7 | }; 8 | 9 | int main(void) 10 | { 11 | union example u={.x=100}; 12 | printf("The elements of the union are (%d,%d).\n",u.x, u.y); 13 | 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /Useful C libraries/Assert/an_example_of_using_assert_1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | int main(void) 6 | { 7 | int i=7; 8 | 9 | for(int j=0;j<30;++j) 10 | { 11 | printf("i=%d \t j=%d \n",i,j); 12 | assert(j 2 | 3 | int main(void) 4 | { 5 | int ch=0; 6 | 7 | while((ch=getchar())!=EOF) 8 | { 9 | putchar(ch); 10 | } 11 | 12 | ungetc(ch,stdin); 13 | 14 | printf("Thank you.\n"); 15 | 16 | return 0; 17 | } -------------------------------------------------------------------------------- /Macros/Preprocessor Operators/using_the_pound_operator_string_expansion.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define PRINTF(var) ( printf(#var "is %d.\n",var)) 4 | #define HELLO(x) (printf("Hello" #x "!\n")) 5 | #define STR(x) (#x) 6 | 7 | int main(void) 8 | { 9 | puts(STR("Guten tag")); 10 | 11 | int i=10; 12 | PRINTF(i); 13 | 14 | HELLO("George"); 15 | 16 | return 0; 17 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Advanced-C-Programming-Course 2 | Code work associated with the course "Advanced C Programming Course" on Udemy, Authored by Tim Buchalka's Learn Programming Academy and Jason Fedin 3 | 4 | ## Course URL 5 | https://www.udemy.com/course/advanced-c-programming-course/ 6 | 7 | # Skill level 8 | Intermediate and Advanced 9 | 10 | # Notes 11 | ![Landing](2021-11-04_16-18-29.png) 12 | -------------------------------------------------------------------------------- /Input and Output/Functions dealing with characters/Output functions/use_putc_with_stdout.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* ================================================ 4 | int putc(int character,FILE *filepointer) 5 | ================================================== */ 6 | 7 | 8 | 9 | int main(void) 10 | { 11 | char myChar='p'; 12 | 13 | putc(myChar,stdout); 14 | 15 | 16 | return 0; 17 | } -------------------------------------------------------------------------------- /Storage classes/External variables/Using extern with global variables/other.c: -------------------------------------------------------------------------------- 1 | extern int myVariable; //this informs us that this variable is defined elsewhere as a global variable and can be accessed and modified from here 2 | extern char myName[]; //this informs us that this variable is defined elsewhere as a global variable and can be accessed and modified from here 3 | 4 | void foo(void) 5 | { 6 | myVariable++; 7 | } 8 | -------------------------------------------------------------------------------- /Advanced Debugging and Analysis/Debugging with the GNU Project Debugger gdb/debug_with_gdb.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int myFunction() 4 | { 5 | //do nothing 6 | } 7 | 8 | int main(void) 9 | { 10 | const int data[]={1,3,5,6,7}; 11 | int i=0, sum=0; 12 | 13 | for(i=0;i>=0; ++i) 14 | { 15 | sum+=data[i]; 16 | } 17 | 18 | printf("The sum is %i.\n", sum); 19 | 20 | return 0; 21 | } -------------------------------------------------------------------------------- /Input and Output/Functions dealing with characters/Output functions/use_fputc_with_a_file.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) 4 | { 5 | FILE *fp=NULL; 6 | char c='\0'; 7 | 8 | fp=fopen("thefile.txt","w"); 9 | 10 | if(fp!=NULL) 11 | { 12 | for(c='A';c<'Z';c++) 13 | { 14 | fputc(c,fp); 15 | } 16 | 17 | } 18 | fclose(fp); 19 | 20 | return 0; 21 | } -------------------------------------------------------------------------------- /Macros/Creating your own macros/create_macro_for_non_standard_C_code.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define UpTo(i,n) for((i)=0;(i)<(n);(i)++) printf("The current step is %d.\n",i) 4 | #define UpTo1(i,n) for((i)=0;(i)<(n);(i)++) 5 | 6 | int main(void) 7 | { 8 | int i; 9 | 10 | UpTo(i,10); 11 | 12 | UpTo1(i,50) 13 | { 14 | printf("The current step is %d.\n",i); 15 | } 16 | 17 | return 0; 18 | } -------------------------------------------------------------------------------- /Advanced Debugging and Analysis/Using core-dump files/a_program_that_returns_segfault_example_4.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) 4 | { 5 | int *ptrInt=NULL; 6 | 7 | ptrInt=(int *) malloc(sizeof(int)); 8 | *ptrInt=43; 9 | free(ptrInt); 10 | 11 | *ptrInt=63; //error here due to accessing an undetermined area of memory. pointer was deleted. it is pointing nowhere now. 12 | 13 | return 0; 14 | } -------------------------------------------------------------------------------- /Input and Output/Functions dealing with characters/Output functions/use_putchar.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) 4 | { 5 | char hello[]="Hello, George. It is a great day to move \n on."; 6 | 7 | int i=0; 8 | 9 | while(hello[i]!='\0') 10 | { 11 | if(hello[i]!='\n') 12 | { 13 | putchar(hello[i]); 14 | } 15 | ++i; 16 | } 17 | 18 | 19 | return 0; 20 | } -------------------------------------------------------------------------------- /Interprocess Communication/raising_an_alarm_signal.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main(void) 7 | { 8 | alarm(10); //raise an alarm signal for the process itself after 10 seconds. it it is not caught, by default it terminates the process 9 | 10 | for(int i=0;i<10;i++) 11 | { 12 | printf("%d.\n",i); 13 | sleep(1); 14 | } 15 | 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /Bit manipulations/Bitwise Operators/Logical_binary_operators_AND.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) 4 | { 5 | short int number1=43; //in binary 0010 1011 6 | short int number2=65; //in binary 0100 0001 7 | 8 | short int result=0; 9 | 10 | 11 | result=number1 & number2; //0000 0001 which is decimal 1 12 | printf("The binary operation %d & %d is %d .\n", number1,number2, result); 13 | 14 | 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /Bit manipulations/Bitwise Operators/Logical_binary_operators_OR.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) 4 | { 5 | short int number1=43; //in binary 0010 1011 6 | short int number2=65; //in binary 0100 0001 7 | 8 | short int result=0; 9 | 10 | 11 | result=number1 | number2; //0110 1011 which is decimal 107 12 | printf("The binary operation %d | %d is %d .\n", number1,number2, result); 13 | 14 | 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /Advanced Pointers/Void pointers/pointer_arithmetic_with_void_pointers.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) 4 | { 5 | int myArray[]={10,43,65}; 6 | 7 | void *this_pointer=&myArray[1]; //this points to the second element of the array thus 43 8 | 9 | this_pointer+=sizeof(int); // pointer arithmetic this offsets with the size of one int thus -> 65 10 | 11 | printf("%d\n",*(int *) this_pointer); //should show 65 12 | 13 | return 0; 14 | } -------------------------------------------------------------------------------- /Threads/Creating a thread/create_a_thread.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void *my_function() 6 | { 7 | puts("Hello, World!"); 8 | return NULL; 9 | } 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | pthread_t this_thread; 14 | 15 | pthread_create(&this_thread,NULL,my_function,NULL); 16 | pthread_join(this_thread,NULL); 17 | 18 | pthread_exit(NULL); 19 | 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /Shared Libraries and Shared Objects/Creating a static library/myDemo/myDemo.layout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Advanced Data Types/Designated Initializers/example_using_designated_initializers_with_arrays.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) 4 | { 5 | int myArray[100]={1,2,3,[3 ... 50]=19, [3]=44,34}; //all elements which are not initialized take the default value which is O; hence [54]=34 ; [55]=0 6 | 7 | for(int i=0;i<100;i++) 8 | { 9 | printf("Element for index [%d]..................%d\n",i,myArray[i]); 10 | } 11 | 12 | 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /Useful C libraries/Assert/switch_off_assertions.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | //define or undefine NDEBUG in front of include 4 | #define NDEBUG //#undef NDEBUG to enable assertions on systems where they have been disabled by default 5 | #include 6 | 7 | int main(void) 8 | { 9 | int i=0; 10 | 11 | assert(i<0); // when the condition in the assert is false, the program abort() 12 | printf("The variable is %d",i); 13 | 14 | return 0; 15 | } -------------------------------------------------------------------------------- /Working with Larger Programs/Heap and stack memory allocation/working_with_the_stack_memory.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | double multiplyDouble(double myNumber) 4 | { 5 | double twice=myNumber*2; 6 | return twice; 7 | } 8 | 9 | int main(int argc, char *argv[]) 10 | { 11 | int age=43; 12 | double salary=72.3; 13 | 14 | double myArray[]={10.3,33.2,345.2}; 15 | 16 | printf("The twice is %.3f.\n",multiplyDouble(salary)); 17 | 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /Advanced Data Types/Variable length arrays/variable_length_array_example_2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void array(int size) 4 | { 5 | char myArr[size]; 6 | int i=0; 7 | 8 | while(i<=size) 9 | { 10 | myArr[i]='A'+i; 11 | printf("The member of the array is %c.\n",myArr[i]); 12 | i++; 13 | } 14 | 15 | } 16 | 17 | 18 | 19 | int main(void) 20 | { 21 | array(5); 22 | array(10); 23 | array(20); 24 | 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /Shared Libraries and Shared Objects/Creating a static library/myStaticLibrary/myStaticLibrary.layout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Advanced Debugging and Analysis/Using core-dump files/a_program_that_returns_segfault_example_1.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) 4 | { 5 | char *myString=NULL; 6 | 7 | myString="I am feeling great today.I am loving C."; 8 | 9 | printf("my string is : %s .\n",myString); 10 | 11 | myString="Error when trying to change this string because it is accessing a read-only memory region"; 12 | 13 | printf("my string is : %s .\n",myString); 14 | 15 | return 0; 16 | } -------------------------------------------------------------------------------- /Interprocess Communication/raising_a_signal.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(void) 6 | { 7 | pid_t processId; 8 | 9 | processId=getpid(); 10 | 11 | printf("The process id is %d. We will test raising a SIGSTOP signal for this process and starting over this process from command line.\n",processId); 12 | 13 | int result=raise(SIGSTOP); 14 | 15 | printf("I am back after starting from the keyboard"); 16 | 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /Macros/Preprocessor Operators/using_the_pound_pound_concatenation_operator.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | #define concatenate(a,b) (a##b) 5 | 6 | #define MAKE_FUNCTION(name) int my_##name(int foo){} 7 | #define MAKE_FUNCTION_STRING(name) "int my_"#name "(int foo){}" 8 | 9 | 10 | int main(void) 11 | { 12 | MAKE_FUNCTION(start); 13 | 14 | printf("This is the command:\n %d\n",concatenate(1,0)); 15 | 16 | printf("This is the command:%s\n",MAKE_FUNCTION_STRING(end)); 17 | 18 | return 0; 19 | } -------------------------------------------------------------------------------- /Advanced Data Types/Variable length arrays/variable_length_array_example_multiple_dimensions.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) 4 | { 5 | size_t rows=0; 6 | size_t columns=0; 7 | 8 | printf("Please enter the first size of the array you wish to generate.\n"); 9 | scanf("%zd",&rows); 10 | 11 | printf("Please enter the second size of the array you with to generate. \n"); 12 | scanf("%zd",&columns); 13 | 14 | float numbers[rows][columns]; 15 | 16 | 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /The Preprocessor/Conditional Compilation/using_ifdef.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define JUST_CHECKING 4 | #define LIMIT 10 5 | 6 | int main(void) 7 | { 8 | int i=0; 9 | int total=0; 10 | 11 | for(i;i 2 | #include 3 | #include 4 | 5 | 6 | void foo(char *word) 7 | { 8 | word=(char *) malloc(255); 9 | strcpy(word,"Fuck off"); 10 | } 11 | 12 | int main(void) 13 | { 14 | char *myChar=NULL; 15 | 16 | foo(myChar); 17 | 18 | printf("The phrase is %s.\n",myChar); // this program will crash either here when printing a null 19 | free(myChar); //or here when freeing memory not allocated 20 | } -------------------------------------------------------------------------------- /Advanced Data Types/Designated Initializers/example_using_designated_initializers_with_an_array_of_structures.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | struct point 5 | { 6 | int x; 7 | int y; 8 | int z; 9 | }; 10 | 11 | 12 | 13 | 14 | int main(void) 15 | { 16 | struct point myArrayOfStructs[5]={[1].x=43, [1].y=44, [1].z=66}; 17 | 18 | for(int i=0;i<5;i++) 19 | { 20 | printf("%d \t %d \t %d\n", myArrayOfStructs[i].x,myArrayOfStructs[i].y,myArrayOfStructs[i].z); 21 | } 22 | 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /Advanced Pointers/Void pointers/size_of_void_pointers.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) 4 | { 5 | void *void_pointer=NULL; 6 | int *int_pointer=NULL; 7 | float *float_pointer=NULL; 8 | char *char_pointer=NULL; 9 | 10 | printf("Size of the void * is %d.\n",sizeof(void_pointer)); 11 | printf("Size of the int * is %d.\n",sizeof(int_pointer)); 12 | printf("Size of the float * is %d.\n",sizeof(float_pointer)); 13 | printf("Size of the char * is %d.\n",sizeof(char_pointer)); 14 | 15 | return 0; 16 | } -------------------------------------------------------------------------------- /Advanced Pointers/Use Cases/2nd_use_case_of_using_double_pointers_case_RESOLVED.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void foo(char **word) 6 | { 7 | *word= (char *) malloc(255); 8 | strcpy(*word,"Fuck off"); 9 | } 10 | 11 | int main(void) 12 | { 13 | char *this_char=NULL; 14 | 15 | foo(&this_char); //this passes a pointer to pointer 'this_char' hence it allocated memory 'this_char; 16 | printf("The phrase is %s \n", this_char); 17 | free(this_char); 18 | 19 | return 0; 20 | } -------------------------------------------------------------------------------- /Unions/Accessing a union/accessing_the_members_of_a_union_example_2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | union example 4 | { 5 | int number1; 6 | int number2; 7 | }; 8 | 9 | int main(void) 10 | { 11 | union example u; 12 | 13 | u.number1=43; 14 | printf("The member of the union object are 'u.number1'=%d \t and 'u.number2'=%d. \n",u.number1, u.number2); 15 | 16 | u.number2=100; 17 | printf("The member of the union object are 'u.number1'=%d \t and 'u.number2'=%d. \n",u.number1, u.number2); 18 | 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /Working with extern variables/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "types.h" 5 | #include "otherfile.h" 6 | #include "file.h" 7 | 8 | thiscar dacia; 9 | 10 | int main() 11 | { 12 | strcpy(dacia.color,"white"); 13 | dacia.speed=120; 14 | dacia.power=75; 15 | 16 | printf("dacia spped is %d.\n",dacia.speed); 17 | printsome(); 18 | printf("dacia spped is %d.\n",dacia.speed); 19 | wow(); 20 | printf("dacia spped is %d.\n",dacia.speed); 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /Macros/Creating your own macros/creating_your_own.macros.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define PI 3.14 4 | #define AREA_CIRCLE(r) ((PI)*(r)*(r)) //place the variable between parentheses to keep the order of operations when replacing it with expressions 5 | 6 | 7 | int main(void) 8 | { 9 | 10 | double area=0.0; 11 | area=AREA_CIRCLE(4); 12 | 13 | printf("The area of the circle is %f.\n",area); 14 | 15 | int c=2; 16 | area=AREA_CIRCLE(c+5); 17 | 18 | printf("The area of the circle is %f.\n",area); 19 | 20 | return 0; 21 | } -------------------------------------------------------------------------------- /Storage classes/Static variables/Using static functions/using_static_functions.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "supplementary.c" 3 | 4 | /* ======================================================= 5 | Notes: anytime when the storage class is not specified for a function it means it is 'extern' so it can be used and seen from other files as well 6 | ========================================================== */ 7 | 8 | extern void foo(); 9 | 10 | int main(int argc, char *argv[]) 11 | { 12 | foo(); 13 | bar(); 14 | 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /The Preprocessor/Conditional Compilation/using_ifdef_else.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef UNIX 4 | # define DATADIR "/unx/dir" 5 | #else 6 | # define DATADIR "\\usr\\bin" 7 | #endif 8 | 9 | /* ============================ 10 | Good practices: The UNIX constant can be added at runtime, when compiling the code 11 | gcc -D UNIX using_if_else.c -o exe 12 | ============================= */ 13 | 14 | int main(void) 15 | { 16 | char *thisString=DATADIR; 17 | 18 | printf("The constant value is %s.\n",thisString); 19 | 20 | return 0; 21 | } -------------------------------------------------------------------------------- /Input and Output/Functions dealing with characters/use_getc_to_read_from_file.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) 4 | { 5 | char myChar='\0'; 6 | int myAsciiCode=0; 7 | 8 | FILE *file_pointer=NULL; 9 | 10 | if(file_pointer=fopen("thefile.txt","rw")) 11 | { 12 | myChar=getc(file_pointer); 13 | printf("%c",myChar); 14 | 15 | while(myChar!=EOF) 16 | { 17 | myChar=getc(file_pointer); 18 | printf("%c",myChar); 19 | } 20 | } 21 | 22 | fclose(fp); 23 | 24 | return 0; 25 | } -------------------------------------------------------------------------------- /Storage classes/External variables/Using extern with global variables/external_variables.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "other.c" 3 | #include "other_version_2.c" 4 | 5 | int myVariable; //this is a global variable because it is defined outside of any function' 6 | 7 | int main(void) 8 | { 9 | myVariable=100; 10 | 11 | printf("The value of the variable is %d.\n",myVariable); 12 | foo(); 13 | printf("The value of the variable is %d.\n",myVariable); 14 | foo_2(); 15 | printf("The value of the variable is..... %d.\n",myVariable); 16 | 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /Advanced Data Types/Designated Initializers/example_using_designated_initializers_with_structures.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct point 4 | { 5 | int x; 6 | int y; 7 | int z; 8 | }; 9 | 10 | 11 | 12 | int main(void) 13 | { 14 | struct point p1={.x=12,.y=23}; 15 | struct point p2={x:43,y:44}; 16 | 17 | //the elements of the struct which are not initialized take the default value which is 0 18 | 19 | printf("The first element is %d,%d,%d \n",p1.x,p1.y,p1.z); 20 | printf("The second element is %d,%d,%d \n", p2.x,p2.y,p2.z); 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /Advanced Pointers/Void pointers/using_void_pointer_example1.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) 4 | { 5 | int a=10; 6 | int pi=3.14; 7 | int myChar='G'; 8 | 9 | 10 | void *void_pointer=NULL; 11 | 12 | void_pointer=&a; 13 | printf("The value stored in 'void_pointer' is %d.\n",*(int *)void_pointer); 14 | 15 | void_pointer=π 16 | printf("The value stored in 'void_pointer' is %.2f.\n",*(float *)void_pointer); 17 | 18 | void_pointer=&myChar; 19 | printf("The value stored in 'void_pointer' is %c.\n",*(char *)void_pointer); 20 | 21 | return 0; 22 | } -------------------------------------------------------------------------------- /Interprocess Communication/get_process_id.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main(void) 7 | { 8 | int processId, parentProcessId; 9 | 10 | printf("This program is used to get process Id information.\n"); 11 | processId=getpid(); 12 | parentProcessId=getppid(); 13 | 14 | printf("The process id is %d, while the parent process id is %d.\n",processId, parentProcessId); 15 | 16 | puts("One can cross verify the process ids by executing commands in the shell"); 17 | system("ps -ef"); 18 | 19 | 20 | 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /Storage classes/Automatic variables/automatic_storage_classes.c: -------------------------------------------------------------------------------- 1 | /* The storage class refers to scope, visibility and life-time of a variable or of a function */ 2 | 3 | double multiply(double number); 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | auto int x; //this is a local variable with an auto storage class, but the 'auto' keyword is not necessarily needed to be added as it is implicit for local variables 8 | 9 | return 0; 10 | } 11 | 12 | double multiply(double number) 13 | { 14 | double twice; //this is a local variable with auto storage class 15 | 16 | twice=number*2; 17 | return twice; 18 | } 19 | -------------------------------------------------------------------------------- /Advanced Debugging and Analysis/use_preprocessor_to_debug.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int sum(int i, int j, int k) 4 | { 5 | return(i+j+k); 6 | } 7 | 8 | int main(void) 9 | { 10 | int i=0; 11 | int j=0; 12 | int k=0; 13 | int number_of_integers_read=0; 14 | 15 | number_of_integers_read=scanf("%d %d %d",&i,&j,&k); 16 | 17 | #ifdef DEBUG 18 | fprintf(stderr,"The number of integers read is %d.\n",number_of_integers_read); 19 | fprintf(stderr,"i=%d ; j=%d ; k=%d.\n",i,j,k); 20 | #endif 21 | 22 | printf("The sum of your numbers is %d.\n",sum(i,j,k)); 23 | return 0; 24 | } -------------------------------------------------------------------------------- /Useful C libraries/Assert/an_example_of_using_assert_2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | int main(void) 7 | { 8 | puts("Enter two numbers:"); 9 | 10 | double a=0.0; 11 | double b=0.0; 12 | double z=0.0; 13 | 14 | int number_of_integers=scanf("%lf %lf",&a,&b); 15 | 16 | while( number_of_integers==2 && (a!=0 || b!=0) ) 17 | { 18 | z=a*a-b*b; 19 | assert(z>=0); 20 | 21 | printf("The result is z=%f", z); 22 | 23 | } 24 | 25 | puts("Enter the next numbers."); 26 | puts("Done"); 27 | 28 | return 0; 29 | } -------------------------------------------------------------------------------- /Storage classes/External variables/Using extern with functions/using_extern_with_functions.c: -------------------------------------------------------------------------------- 1 | /* ========================================================================= 2 | By using extern with functions , one can use functions without having the need to declare them in header files 3 | ============================================================================ */ 4 | 5 | #include 6 | #include "other_file.c" 7 | 8 | 9 | int myGlobalVariable; 10 | 11 | extern void displayFunction(); 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | myGlobalVariable=65; 16 | displayFunction(); 17 | 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /Advanced Data Types/the_define_preprocessor_directive.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define TWO_PI 2*3,1415 3 | #define PI 3.1415f 4 | 5 | /* ===================================================================== 6 | * Good practice: the #define preprocessor directive replaces at each occurrence the symbol with the value to which it is defined. 7 | * Whilst the 'const float pi=3.14f' is datatype safe, by incorporating information about the data type too 8 | * ===================================================================== */ 9 | const float pi=3.1415f; 10 | 11 | int main(int argc, char **argv) 12 | { 13 | 14 | 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /Input and Output/Functions dealing with characters/Output functions/use_putc_with_a_file.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* ============================================== 4 | int putc(int character,FILE *fp); 5 | ================================================ */ 6 | 7 | 8 | 9 | int main(void) 10 | { 11 | char myChar='\0'; 12 | FILE *fp=NULL; 13 | 14 | if(fp=fopen("thefile.txt","rw")) 15 | { 16 | myChar=getc(fp); 17 | while(myChar!=EOF) 18 | { 19 | putc(myChar,fp); 20 | myChar=getc(fp); 21 | } 22 | 23 | fclose(fp); 24 | } 25 | 26 | 27 | 28 | 29 | return 0; 30 | } -------------------------------------------------------------------------------- /Storage classes/External variables/Using extern with global variables/external_variables_second_version_of_definition.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "other.c" 3 | #include "other_version_2.c" 4 | 5 | extern int myVariable=43; //this is the second manner of defining an external variable; with 'extern' keyword and initialization 6 | char myName[]="George Calin"; 7 | 8 | int main(void) 9 | { 10 | 11 | printf("The value of the variable is %d.\n",myVariable); 12 | foo(); 13 | printf("The value of the variable is %d.\n",myVariable); 14 | foo_2(); 15 | printf("The value of the variable is..... %d.\n",myVariable); 16 | 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /Macros/Overview/main.h: -------------------------------------------------------------------------------- 1 | #ifndef _MAIN_H 2 | #define _MAIN_H 3 | #include 4 | 5 | /* ================================================================= 6 | Note: the content of the definition of the macro extends until the first new line character after the # symbol before the 'define' 7 | The value of the macro can be expanded over multiple lines by using the \ special character 8 | =================================================================== */ 9 | 10 | #define PRNT(a,b) \ 11 | printf("The value of a is %d\n",a); \ 12 | printf("The value of b is %d.",b); 13 | 14 | #endif -------------------------------------------------------------------------------- /Threads/Common Thread Functions/using_pthread_cancel.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void *thread_function(void *argument) 7 | { 8 | puts("Hello from thread."); 9 | int result=pthread_cancel(pthread_self()); 10 | 11 | printf("Result=%d. >>>> I am dead now. I committed suicide\n",result); 12 | return NULL; 13 | } 14 | 15 | int main(int argc, char **argv) 16 | { 17 | pthread_t thread; 18 | 19 | int result=pthread_create(&thread,NULL,thread_function,NULL); 20 | pthread_join(thread,NULL); 21 | 22 | puts("Hello from main thread"); 23 | 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /Bit manipulations/Bitwise Operators/Logical_binary_operators_XOR.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) 4 | { 5 | short int number1=43; //in binary 0010 1011 6 | short int number2=65; //in binary 0100 0001 7 | 8 | short int result=0; 9 | 10 | 11 | result=number1 ^ number2; //0110 1010 which is decimal 106 12 | printf("The binary operation %d ^ %d is %d .\n", number1,number2, result); 13 | 14 | 15 | /* ======================================= 16 | note: one can use the XOR binary operator to compare numbers 17 | integer number ^ itself = 0 18 | ========================================== */ 19 | 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /The Preprocessor/Conditional Compilation/if_else_preprocessir_directive.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define US 1 4 | #define UK 2 5 | #define FRANCE 3 6 | #define GERMANY 4 7 | #define COUNTRY FRANCE 8 | 9 | 10 | int main(void) 11 | { 12 | #if COUNTRY==US || COUNTRY==UK 13 | #define GREETING "Hello" 14 | #elif COUNTRY==FRANCE //Always use #elif and not #else when using multiple options in the ifclause of preprocessor directives 15 | #define GREETING "Bonjour" 16 | #elif COUNTRY=GERMANY 17 | #define GREETING "Guten Tag" 18 | #endif 19 | 20 | printf("The greeting is %s.\n", GREETING); 21 | 22 | return 0; 23 | } -------------------------------------------------------------------------------- /Input and Output/Functions dealing with characters/thefile.txt: -------------------------------------------------------------------------------- 1 | A Boston hospital will conduct human trials to test the safety and efficacy of a vaccine to counter Alzheimer’s disease next month. It will mark the first clinical trial of a nasal vaccine for the dementia-causing disorder. 2 | 3 | The longest lunar eclipse in over 500 years will occur in the early hours of November 19, lasting several hours. 4 | 5 | The peak of the partial eclipse will take place in the predawn hours on Friday when 97% of the moon will be eclipsed by the Earth’s shadow. The previous longest partial eclipse took place in 2018 and lasted less than two hours, while this will last for several hours. 6 | 7 | 8 | -------------------------------------------------------------------------------- /Threads/Common Thread Functions/using_pthread_self_function.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | void * thread_function(void *argument) 8 | { 9 | printf("In the thread, the id of the thread is %d.\n",pthread_self()); 10 | pthread_exit(NULL); 11 | return NULL; 12 | } 13 | 14 | int main(int argc, char **argv) 15 | { 16 | pthread_t this_thread; 17 | 18 | pthread_create(&this_thread,NULL,thread_function,NULL); 19 | pthread_join(this_thread,NULL); 20 | 21 | printf("In the main thread, the id of the thread is %d.\n",this_thread); 22 | 23 | pthread_exit(NULL); 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /Unions/Accessing a union/accessing_the_members_of_a_union_example_1.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | union mixed 5 | { 6 | int i; 7 | float f; 8 | char c; 9 | }; 10 | 11 | 12 | int main(void) 13 | { 14 | union mixed thisUnion; 15 | 16 | thisUnion.c='c'; //there can be only one member initialized in a union at a given time because all member share the same memory 17 | printf("The member of the union object is ===> %c \n", thisUnion.c); 18 | 19 | thisUnion.i=100; //assigning another member of the union, hence purging the old one 20 | printf("The NEW member of the union object now is ===> %d \n", thisUnion.i); 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /Input and Output/Functions dealing with characters/Output functions/thefile.txt: -------------------------------------------------------------------------------- 1 | A Boston hospital will conduct human trials to test the safety and efficacy of a vaccine to counter Alzheimer’s disease next month. It will mark the first clinical trial of a nasal vaccine for the dementia-causing disorder. 2 | 3 | The longest lunar eclipse in over 500 years will occur in the early hours of November 19, lasting several hours. 4 | 5 | The peak of the partial eclipse will take place in the predawn hours on Friday when 97% of the moon will be eclipsed by the Earth’s shadow. The previous longest partial eclipse took place in 2018 and lasted less than two hours, while this will last for several hours. 6 | 7 | 8 | -------------------------------------------------------------------------------- /Advanced Pointers/Functions Pointers/example_of_using_function_pointers_1.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int this_function(); 4 | 5 | int main(void) 6 | { 7 | //declare the function pointer 8 | int (*function_pointer)(); 9 | 10 | //assignment of function pointer 11 | function_pointer=this_function; //can be used as function_pointer=&this_function but it is not a must 12 | 13 | printf("The address of the function pointer called 'function_pointer' is %p.\n",function_pointer); 14 | 15 | //invocation 16 | (*function_pointer)(); 17 | 18 | 19 | return 0; 20 | } 21 | 22 | int this_function() 23 | { 24 | puts(" I have had enough of C course lately. But I still like it."); 25 | return 0; 26 | } -------------------------------------------------------------------------------- /Advanced Control Flow/The goto statement/using_the_goto_statement.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | int main(int argc, char **argv) 5 | { 6 | int maxIterations=10; 7 | double number=0.0; 8 | double average=0.0; 9 | double sum=0.0; 10 | int i=0; 11 | 12 | for(i=1;i<=maxIterations;i++) 13 | { 14 | printf("Enter the number: \t"); 15 | scanf("%lf",&number); 16 | 17 | if(number<0.0) 18 | { 19 | goto mylabel; 20 | } 21 | 22 | sum+=number; 23 | } 24 | 25 | mylabel: 26 | average=sum/(i-1); 27 | printf("The average for the numbers you entered is %.3f. \n",average); 28 | printf("The sum for the numbers you entered is %.3f. \n",sum); 29 | 30 | return 0; 31 | } -------------------------------------------------------------------------------- /Advanced Pointers/example.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) 4 | { 5 | int a=10; 6 | 7 | int *ptr=NULL; 8 | int **ptrptr=NULL; 9 | 10 | ptr=&a; 11 | ptrptr=&ptr; 12 | 13 | printf("The memory address where the variable \"a\" is stored is %p.\n",&a); 14 | printf("The memory address where the variable \"ptr\"i is stored is %p.\n",&ptr); 15 | printf("The memory address where the variabe \"ptrptr\" is stored is %p.\n",&ptrptr); 16 | 17 | printf("The value stored at the memory address stored by \"ptr\" is %d.\n",*ptr); //should be a 18 | printf("The value stored at the memory address stored by \"ptrptr\" is %p.\n",*ptrptr); //should be &a 19 | printf("The value of **\"ptrptr\" is %d.\n ",**ptrptr); 20 | 21 | return 0; 22 | } -------------------------------------------------------------------------------- /Input and Output/Functions dealing with characters/use_getchar_to_read_from_terminal.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* ============================================================ 4 | int getchar(void) : unlike int getc(FILE *fp), getchar() function only reads from the terminal 5 | Depending on the OS, system can enter the EOF character , which in Linux can be achieved by pressing CTRL+D 6 | Always use ints when working with getchar() and comparing to the EOF character!!! 7 | =============================================================== */ 8 | 9 | int main(void) 10 | { 11 | int myCh=0; 12 | 13 | while((myCh=getchar())!=EOF) //it stops when one presses ctrl+d on Linux OS 14 | { 15 | printf("%c",myCh); 16 | } 17 | 18 | 19 | 20 | return 0; 21 | } -------------------------------------------------------------------------------- /Input and Output/Formatting functions/using_fprintf_and_stderr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* ========================================================================================== 5 | Notes: stderr is used when one the redirect the error messages to a different output then the normal output of the program. For instance if the program outputs to a file, stderr will display errors on the terminal window 6 | =========================================================================================== */ 7 | 8 | int main(void) 9 | { 10 | FILE *fp=NULL; 11 | 12 | fp=fopen("thefilew.txt", "r"); 13 | 14 | if(fp==NULL) 15 | { 16 | fprintf(stderr,"Error when opening the file."); 17 | exit(-1); 18 | } 19 | 20 | return 0; 21 | } -------------------------------------------------------------------------------- /Advanced Data Types/Variable length arrays/challenge.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int array_magic() 4 | { 5 | size_t size_of_the_array=0; 6 | int total=0; 7 | 8 | printf("Please enter the size of the array you wish to summate its elements.\n"); 9 | scanf("%zd",&size_of_the_array); 10 | 11 | int myArray[size_of_the_array]; 12 | 13 | for(int i=0;i 2 | #include 3 | 4 | int main(void) 5 | { 6 | /* int fputs(const char *myString, FILE *filePointer) => returns EOF in case of an error AND non negative number in case stuffs went alright */ 7 | /* fputs() does not add automatically the '\n' character. The terminating null character is not written to the file */ 8 | 9 | FILE *filePointer=NULL; 10 | char *myString=NULL; 11 | 12 | filePointer=fopen("thefile.txt","a"); 13 | 14 | if(!filePointer) 15 | { 16 | puts("An error occurred."); 17 | exit(1); 18 | } 19 | 20 | fputs("This Udemy course is a great one to help you learn C",filePointer); 21 | 22 | fclose(filePointer); 23 | 24 | 25 | 26 | return 0; 27 | } -------------------------------------------------------------------------------- /Storage classes/Register variables/using_the_register_storage_class.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | /* =========================================== 5 | Note: The register storage class is used with frequently accessed variables to store these variables in a CPU register, unlike the normal way when the variables are stored in the RAM. 6 | It gains speed, but the size of the variable gets limited to the size of the CPU register. Additionally there can not be applied the operator & address of to a variable of register type 7 | ============================================== */ 8 | 9 | 10 | int main(void) 11 | { 12 | register int counter; 13 | 14 | for(counter=0; counter<=100;counter++) 15 | { 16 | printf("The value of the counter is %d.\n",counter); 17 | } 18 | 19 | 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /Input and Output/Formatting functions/using_fscanf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* ========================================================================================= 5 | Notes: int fscanf(FILE *filepointer, const char format, argument1,....) 6 | -fscanf() function is similar to scanf() with regard to it is reading data from something, but fscanf() reads from a file into a variable 7 | =========================================================================================== */ 8 | 9 | int main(void) 10 | { 11 | FILE *filepointer=NULL; 12 | char buffer[100]; 13 | 14 | filepointer=fopen("thefile.txt","r"); 15 | 16 | while(fscanf(filepointer,"%s",buffer)!=EOF) 17 | { 18 | printf("%s",buffer); 19 | } 20 | 21 | fclose(filepointer); 22 | 23 | 24 | return 0; 25 | } -------------------------------------------------------------------------------- /Bit manipulations/Bitwise Operators/Logical_binary_operators_binary_complement.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) 4 | { 5 | short int number1=43; //in binary 0010 1011 6 | short int number2=65; //in binary 0100 0001 7 | 8 | short int complement1=0; 9 | short int complement2=0; 10 | 11 | 12 | /* ================================================= 13 | to obtain the decimal number from the binary complement= flip the bits , convert to binary and add +1 14 | ================================================== */ 15 | 16 | complement1=~number1; // 1101 0100 which is decimal -44 17 | complement2=~number2; // 1011 1110 which is decimal -66 18 | printf("The binary operation ~%d & %d ; \t ~%d is %d.\n", number1,complement1, number2, complement2); 19 | 20 | 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /Input and Output/Formatting functions/using_sprintf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* ====================================================================================== 5 | Notes: 6 | - sprintf() goes from "String print formatted" 7 | - int sprintf(char *string, const char *format,....) returns an integer which is he number of characters in the 'string' without accounting the null terrmination character '\0' 8 | - int sprintf() returns a negative number in case of failure 9 | ========================================================================================= */ 10 | 11 | int main(void) 12 | { 13 | char *myString=NULL; 14 | int result=0; 15 | 16 | myString=(char *) malloc(255); 17 | 18 | result=sprintf(myString,"the number is %d.\n",44); 19 | 20 | puts(myString); 21 | 22 | return 0; 23 | } -------------------------------------------------------------------------------- /Advanced Pointers/conceptual_pointer_to_pointer.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) 4 | { 5 | int **double_pointer=NULL; 6 | 7 | int var1=10,var2=43,var3=65; 8 | 9 | int *pVar1=&var1; 10 | int *pVar2=&var2; 11 | int *pVar3=&var3; 12 | 13 | double_pointer=&pVar1; 14 | 15 | printf("The value of the double pointer is %p and this is the memory address it points to (=%p) \n", double_pointer,&pVar1); 16 | printf("The memory address where is stored the double pointer is %p. \n",&double_pointer); 17 | printf("The value stored at the memory address where the double pointer is pointing to is %p while the address the address stored in the intermediate pointer is %p .\n",*double_pointer,pVar1); 18 | printf("The final value to where the chain of pointer to pointer is pointing to is %d.\n",**double_pointer); 19 | 20 | 21 | return 0; 22 | } -------------------------------------------------------------------------------- /Working with Larger Programs/Heap and stack memory allocation/working_with_the_heap_memory.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | double multiplyDouble(double *myNumber) 5 | { 6 | double *twice=(double *) malloc(1*sizeof(double)); 7 | *twice=*myNumber*2; 8 | return *twice; 9 | } 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | int *age=(int *) malloc(1*sizeof(int)); 14 | *age=30; 15 | 16 | double *salary=(double *) malloc(1*sizeof(double)); 17 | *salary=72.4; 18 | 19 | double *myArray=(double *) malloc(3*sizeof(double)); 20 | myArray[0]=23.4; 21 | myArray[1]=44.3; 22 | myArray[2]=22.3; 23 | 24 | double *twice=(double *) malloc(1*sizeof(double)); 25 | *twice=multiplyDouble(salary); 26 | 27 | printf("The double is %.3f .\n",*twice); 28 | 29 | free(twice); 30 | free(myArray); 31 | free(salary); 32 | free(age); 33 | 34 | return 0; 35 | 36 | } 37 | -------------------------------------------------------------------------------- /Input and Output/Functions dealing with characters/use_fgetc_to_read_from_file.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* ====================================================================================== 4 | int fgetc(FILE *fp) : is a function similar to int getc(FILE *fp), but fgetc() only reads from a file 5 | ======================================================================================== */ 6 | 7 | int main(void) 8 | { 9 | char c='\0'; 10 | FILE *fp=NULL; 11 | 12 | fp=fopen("thefile.txt","r"); 13 | 14 | if(fp==NULL) 15 | { 16 | printf("I could not open the file to read from it.\n"); 17 | return 1; 18 | } 19 | 20 | while(1) 21 | { 22 | c=fgetc(fp); 23 | 24 | if(c==EOF) 25 | { 26 | break; 27 | } 28 | 29 | printf("%c",c); 30 | } 31 | 32 | fclose(fp); 33 | 34 | return 0; 35 | } -------------------------------------------------------------------------------- /Threads/Common Thread Functions/using_pthread_detach.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | void * thread_function(void *argument) 9 | { 10 | pthread_detach(pthread_self()); 11 | sleep(2); 12 | 13 | puts("Hello from the thread."); 14 | 15 | return NULL; 16 | } 17 | 18 | int main(int argc, char **argv) 19 | { 20 | pthread_t myThread; 21 | 22 | int result=pthread_create(&myThread,NULL,thread_function,NULL); 23 | 24 | if(result==0) 25 | { 26 | puts("The new thread has been created correctly."); 27 | } 28 | else 29 | { 30 | puts("There was an error when creating the new thread"); 31 | exit(1); 32 | } 33 | 34 | puts("Hello from the MAIN THREAD"); 35 | 36 | pthread_join(myThread,NULL); 37 | 38 | 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /Threads/Passing arguments and returning values/returning_values_from_threads.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void function_in_thread(void *argument) 7 | { 8 | char *message="Hello from thread.\n"; 9 | 10 | char *temporary=strdup(message); //temporary is a pointer to a dynamically create copy of the message on the heap with malloc() 11 | 12 | return (void *) temporary; 13 | } 14 | 15 | int main(int argc, char **argv) 16 | { 17 | char *temporary=NULL; 18 | pthread_t myThread; 19 | 20 | pthread_create(&myThread,NULL,function_in_thread,NULL); 21 | 22 | pthread_join(myThread,&temporary); 23 | 24 | printf("The thread returned this value: \t %s.\n",temporary); 25 | 26 | pthread_exit(NULL); 27 | 28 | puts("The thread is over, I am now in the main thread."); 29 | 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /Advanced Data Types/Flexible array members/challenge.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | struct myArray 6 | { 7 | int length; 8 | int array[]; //this is the flexible array member 9 | }; 10 | 11 | 12 | int main(void) 13 | { 14 | size_t size_of_flexible_array_member=0; 15 | 16 | printf("Read the size of the flexible array member from the keyboard : "); 17 | scanf("%zd",&size_of_flexible_array_member); 18 | 19 | struct myArray *ptrStruct=NULL; 20 | 21 | ptrStruct=(struct myArray *) malloc(sizeof(struct myArray)+size_of_flexible_array_member*sizeof(int)); 22 | 23 | for(int i=0;iarray[i]=0; 26 | } 27 | 28 | 29 | for(int i=0;i 2 | #include 3 | 4 | /* ================================================================== 5 | int ungetc(int ch, FILE *fp) : the function puts back to the stream fp the character ch 6 | the ungetc() returns EOF if it fails, or the character it puts back to the stream otherwise 7 | ==================================================================== */ 8 | 9 | int main(void) 10 | { 11 | char myC='\0'; 12 | 13 | while(isspace(myC=(char) getchar())); //reads from the stream , in this case stdin until a non-white character is found 14 | 15 | ungetc(myC,stdin); //as the first non white space character was already read, it puts it back to the stream to read it again 16 | 17 | 18 | printf("The character is %c",myC); 19 | 20 | 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /Advanced Pointers/Functions Pointers/example_of_using_function_pointers_2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | void function1(int var); 5 | void function2(int var); 6 | 7 | typedef void (*Func)(int); 8 | 9 | int main(void) 10 | { 11 | //declare the function pointer 12 | /* void (*function_pointer)(int) or */ 13 | Func function_pointer=NULL; 14 | 15 | //assignment 16 | function_pointer=function1; //or function_pointer=&function1 17 | 18 | //invocation 19 | (*function_pointer)(100); 20 | 21 | //re-assignment of the function 22 | function_pointer=function2; 23 | 24 | //re-invocation 25 | (*function_pointer)(200); 26 | 27 | return 0; 28 | } 29 | 30 | void function1(int var) 31 | { 32 | printf("The variable is passed through function1 as %d.\n",var); 33 | } 34 | 35 | void function2(int var) 36 | { 37 | printf("The variable is passed through function2 as %d.\n",var); 38 | } -------------------------------------------------------------------------------- /Advanced Pointers/Functions Pointers/example_of_using_function_pointers_3.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | void function1(int var); 5 | void function2(int var); 6 | 7 | typedef void Func(int); 8 | 9 | int main(void) 10 | { 11 | //declare the function pointer 12 | /* void (*function_pointer)(int) or */ 13 | Func *function_pointer=NULL; 14 | 15 | //assignment 16 | function_pointer=function1; //or function_pointer=&function1 17 | 18 | //invocation 19 | (*function_pointer)(100); 20 | 21 | //re-assignment of the function 22 | function_pointer=function2; 23 | 24 | //re-invocation 25 | (*function_pointer)(200); 26 | 27 | return 0; 28 | } 29 | 30 | void function1(int var) 31 | { 32 | printf("The variable is passed through function1 as %d.\n",var); 33 | } 34 | 35 | void function2(int var) 36 | { 37 | printf("The variable is passed through function2 as %d.\n",var); 38 | } -------------------------------------------------------------------------------- /The Preprocessor/Conditional Compilation/using_ifdef_undefine_macro.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | //#define JUST_CHECKING 4 | #define LIMIT 10 5 | 6 | /* ===================================== 7 | Good practice: the preprocessor constants that do not exist can be added also at runtime when compiling the code: 8 | gcc -D JUST_CHECKING using_ifdef_undefine_macro.c -o test2 9 | adds the JUST_CHECKING constant to the preprocesser like it was added in the source code of the file 10 | ======================================== */ 11 | 12 | 13 | int main(void) 14 | { 15 | int i=0; 16 | int total=0; 17 | 18 | for(i;i 2 | #include 3 | 4 | 5 | struct myStruct 6 | { 7 | int arraySize; 8 | int array[];//this is a flexible array member inside the struct.Got support from C99. 9 | }; 10 | 11 | /* ========================================================= 12 | Good practices: when using flexible array members 13 | 1. there can be only a single flexible array member inside a struct 14 | 2. the flexible array member had to be last last member of the struct 15 | 3. structs with flexible array members can not be used inside other structs 16 | ============================================================ */ 17 | 18 | 19 | int main(void) 20 | { 21 | 22 | int desired_size=6; 23 | 24 | struct myStruct* ptrToStruct; 25 | 26 | ptrToStruct=malloc(sizeof(struct myStruct)+desired_size*sizeof(int)); 27 | 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /Interprocess Communication/Handling a signal using the signal function/using_the_signal_function.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void function_dividebyzero(int sig); 6 | 7 | int main(void) 8 | { 9 | int result=0; 10 | int a=0,b=0; 11 | 12 | a=125; 13 | b=0; 14 | 15 | void (*signalHandler) (int); 16 | signalHandler=signal(SIGFPE,function_dividebyzero); 17 | 18 | if(signalHandler==SIG_ERR) 19 | { 20 | perror("Error using signal function"); 21 | return 1; 22 | } 23 | 24 | result=a/b; 25 | 26 | printf("Result of Divide by Zero is %d\n",result); 27 | 28 | return 0; 29 | } 30 | 31 | void function_dividebyzero(int sig) 32 | { 33 | if(sig==SIGFPE) 34 | { 35 | puts("Divide by zero signal was raised"); 36 | exit(0); 37 | } 38 | else 39 | { 40 | puts("Another signal was raised."); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Input and Output/Functions dealing with strings/using_fgets.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* =================================================== 5 | Note: only use fgets() when the data read can not contain the NULL character 6 | ===================================================== */ 7 | 8 | int main(void) 9 | { 10 | char myBuffer[255]; 11 | int i='\0'; 12 | char *p=NULL; 13 | 14 | if(fgets(myBuffer,sizeof(myBuffer),stdin)) 15 | { 16 | p=strchr(myBuffer,'\n'); 17 | 18 | if(p) 19 | { 20 | *p='\0'; 21 | } 22 | else 23 | { 24 | while((i=getchar())!='\n' && !feof(stdin) && !ferror(stdin)); 25 | } 26 | 27 | } 28 | else 29 | { 30 | 31 | //an error occurred while reading with fgets(). Treat the error here 32 | } 33 | 34 | printf("The content of the buffer is %s.\n",myBuffer); 35 | 36 | return 0; 37 | } -------------------------------------------------------------------------------- /Unions/challenge.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | union myUnion 4 | { 5 | char letterGrade; 6 | int roundedGrade; 7 | float exactGrade; 8 | }; 9 | 10 | 11 | int main(void) 12 | { 13 | union myUnion variable1; 14 | union myUnion variable2; 15 | 16 | variable1.letterGrade='s'; 17 | variable1.roundedGrade=44; 18 | variable1.exactGrade=9.81; 19 | 20 | printf("The variable1.letterGrade=%c\n",variable1.letterGrade); 21 | printf("The variable1.roundedGrade=%d\n",variable1.roundedGrade); 22 | printf("The variable1.exactGrade=%f\n",variable1.exactGrade); 23 | 24 | 25 | variable2.letterGrade='G'; 26 | printf("The variable2.letterGrade=%c\n",variable2.letterGrade); 27 | 28 | variable2.roundedGrade=10; 29 | printf("The variable2.letterGrade=%d\n",variable2.roundedGrade); 30 | 31 | variable2.exactGrade=3.14; 32 | printf("The variable2.letterGrade=%f\n",variable2.exactGrade); 33 | 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /Advanced Pointers/Use Cases/use_double_pointer_to_pass_pointer_by_reference_in_function.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | void foo(int **the_pointer) 6 | { 7 | int a=10; 8 | *the_pointer=&a; 9 | } 10 | 11 | int main(void) 12 | { 13 | int *ptr=NULL; 14 | 15 | ptr=(int *) malloc(sizeof(int)); 16 | *ptr=42; 17 | 18 | printf("The memory address where the 'ptr' variable is stored is %p.\n",&ptr); 19 | printf("The value of the 'ptr' variable is %p.\n",ptr); 20 | printf("The value at the memory location stored in the 'ptr' variable is %d.\n",*ptr); 21 | 22 | puts("======== execute function passing a double pointer ========"); 23 | foo(&ptr); 24 | 25 | printf("The memory address where the 'ptr' variable is stored is %p.\n",&ptr); 26 | printf("The value of the 'ptr' variable is %p.\n",ptr); 27 | printf("The value at the memory location stored in the 'ptr' variable is %d.\n",*ptr); 28 | 29 | return 0; 30 | } -------------------------------------------------------------------------------- /Threads/Thread Synchronisation Concepts/using_mutex_example_2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define NTHREADS 25 6 | 7 | pthread_mutex_t my_lock=PTHREAD_MUTEX_INITIALIZER; 8 | int global_variable=0; 9 | 10 | void* thread_function(void *argument) 11 | { 12 | printf("I am in the thread number %ld.\n", pthread_self()); 13 | 14 | pthread_mutex_lock(&my_lock); 15 | global_variable++; 16 | pthread_mutex_unlock(&my_lock); 17 | 18 | return NULL; 19 | } 20 | 21 | int main(int argc, char **argv) 22 | { 23 | pthread_t my_thread[NTHREADS]; 24 | 25 | 26 | for(int i=0;i 2 | #include 3 | 4 | long long convertDecimalToBinary(int decimalNumber); 5 | 6 | 7 | int main(void) 8 | { 9 | long long resultFromConversion; 10 | int decimalNumber=0; 11 | 12 | printf("Please enter the decimal number you wish to convert: "); 13 | scanf("%d",&decimalNumber); 14 | 15 | resultFromConversion=convertDecimalToBinary(decimalNumber); 16 | 17 | printf("The result from converting the decimal number ==>%d to a binary number is ==> %lld",decimalNumber,resultFromConversion); 18 | 19 | 20 | return 0; 21 | } 22 | 23 | long long convertDecimalToBinary(int decimalNumber) 24 | { 25 | long long result=0; 26 | int remainder=0; 27 | int i=1; 28 | 29 | while(decimalNumber!=0) 30 | { 31 | remainder=decimalNumber%2; 32 | decimalNumber=decimalNumber/2; 33 | result+=remainder*i; 34 | i=i*10; 35 | } 36 | 37 | return result; 38 | } 39 | -------------------------------------------------------------------------------- /Input and Output/Functions dealing with strings/using_getline_example_with_character_array.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(void) 5 | { 6 | char myCharacterArray[50]; 7 | char *buffer=myCharacterArray; 8 | size_t buffer_size=50; 9 | size_t number_of_characters_read_with_getline; 10 | 11 | //There is no need to allocate memory anymore with malloc or calloc to host the buffer as it is already initialized to an existing character array which by definition does have memory 12 | 13 | printf("Type something at the keyboard, please \n"); 14 | number_of_characters_read_with_getline=getline(&buffer,&buffer_size,stdin); 15 | 16 | if(number_of_characters_read_with_getline==-1) 17 | { 18 | puts("There was an error when reading the line."); 19 | } 20 | else 21 | { 22 | printf("I read %zu characters from the standard input stream.\n",number_of_characters_read_with_getline); 23 | printf("The content of the buffer is %s.\n",buffer); 24 | } 25 | 26 | 27 | return 0; 28 | } -------------------------------------------------------------------------------- /Threads/Passing arguments and returning values/passing_a_single_argument_to_a_thread.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | void *do_something_in_thread(void *thisPointer); 7 | 8 | int main(int argc, char *argv[]) 9 | { 10 | pthread_t thread1, thread2; 11 | 12 | char *message1="Hello, Dacia!"; 13 | char *message2="Hello, Renault!"; 14 | 15 | int ret1=0; 16 | int ret2=0; 17 | 18 | ret1=pthread_create(&thread1,NULL,do_something_in_thread, (void *) message1); 19 | ret2=pthread_create(&thread2,NULL,do_something_in_thread, (void *) message2); 20 | 21 | pthread_join(thread1, NULL); 22 | pthread_join(thread2, NULL); 23 | 24 | printf("Thread 1 returned this result -> %d.\n",ret1); 25 | printf("Thread 2 returned this result ->%d.\n", ret2); 26 | 27 | pthread_exit(NULL); 28 | 29 | 30 | return 0; 31 | } 32 | 33 | void *do_something_in_thread(void *thisPointer) 34 | { 35 | char *this_message; 36 | this_message=(char *) thisPointer; 37 | 38 | printf("%s.\n",this_message); 39 | } 40 | -------------------------------------------------------------------------------- /Input and Output/Formatting functions/using_sscanf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | /* ======================================================================================= 6 | Notes: sscanf() is a function that can be used to extract data from a string , rather from the standard input or the keyboard 7 | - int sscanf(buffer, "%d %s", &age, name) 8 | - the sscanf() goes from string scanf 9 | - the sscand() returns an integer with the number of characters read or (-1) in case of error 10 | =========================================================================================== */ 11 | 12 | int main(void) 13 | { 14 | char *myString="George Calin IT-Development-Manager 43"; 15 | char name[30],surname[30],title[30]; 16 | int age=0; 17 | int return_value=0; 18 | 19 | return_value=sscanf(myString,"%s %s %s %d",name,surname,title,&age); 20 | 21 | printf("The name is %s.\n",name); 22 | printf("The surname is %s.\n",surname); 23 | printf("The title is %s. \n",title); 24 | printf("The age is %d.\n",age); 25 | 26 | return 0; 27 | } -------------------------------------------------------------------------------- /Input and Output/Functions dealing with strings/using_getline_example_1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | int main(void) 7 | { 8 | char *buffer=NULL; //memory has to be allocated with malloc or calloc for this 9 | size_t buffer_size=12; 10 | size_t number_of_characters_read; 11 | 12 | buffer=(char *) malloc(buffer_size*sizeof(char)); 13 | 14 | if(!buffer) 15 | { 16 | puts("There was an error when allocating memory."); 17 | exit(1); 18 | } 19 | 20 | puts("Please type something:"); 21 | number_of_characters_read=getline(&buffer,&buffer_size,stdin); 22 | 23 | /* =========================================================== 24 | Note: The getline() function reads also the '\n' character, but it does not read the '\0' character 25 | ============================================================ */ 26 | 27 | printf("The number of characters read is %zu.\n",number_of_characters_read); 28 | printf("You read the following buffer: %s.\n", buffer); 29 | 30 | 31 | return 0; 32 | } -------------------------------------------------------------------------------- /Threads/Passing arguments and returning values/passing_an_argument_as_a_struct.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | struct car 7 | { 8 | int speed; 9 | int weight; 10 | char brand[100]; 11 | }; 12 | 13 | void *function_thread(void * thread_argument); 14 | 15 | int main(int argc, char *argv[]) 16 | { 17 | pthread_t thisThread; 18 | 19 | struct car this_car; 20 | 21 | this_car.speed=180; 22 | this_car.weight=1670; 23 | strcpy(this_car.brand,"Tesla"); 24 | 25 | pthread_create(&thisThread,NULL,function_thread,(void *) &this_car); 26 | 27 | pthread_join(thisThread,NULL); 28 | pthread_exit(NULL); 29 | 30 | return 0; 31 | } 32 | 33 | void *function_thread(void * thread_argument) 34 | { 35 | struct car *thread_car; 36 | 37 | thread_car=(struct car *) thread_argument; 38 | 39 | printf("the data passed from the main thread to the second thread is :\n car.speed=%d \t\t car.weight=%d \t\t car.brand=%s. \n",thread_car->speed, thread_car->weight,thread_car->brand); 40 | 41 | } 42 | -------------------------------------------------------------------------------- /Interprocess Communication/listing_the_signals_from_command_line.txt: -------------------------------------------------------------------------------- 1 | georgeca@georgeca-VirtualBox:~/my_sandbox/Advanced-C-Programming-Course/Interprocess Communication$ kill -l 2 | 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 3 | 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 4 | 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 5 | 16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 6 | 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 7 | 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 8 | 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 9 | 38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 10 | 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 11 | 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 12 | 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 13 | 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 14 | 63) SIGRTMAX-1 64) SIGRTMAX 15 | georgeca@georgeca-VirtualBox:~/my_sandbox/Advanced-C-Programming-Course/Interprocess Communication$ 16 | -------------------------------------------------------------------------------- /Advanced Debugging and Analysis/Debugging with the GNU Project Debugger gdb/debug_with_gdb_struct_and_pointers.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | struct date 6 | { 7 | int day; 8 | int month; 9 | int year; 10 | }; 11 | 12 | struct date incrementDay(struct date myCalendaristicDate) 13 | { 14 | ++myCalendaristicDate.day; 15 | return myCalendaristicDate; 16 | } 17 | 18 | int main(void) 19 | { 20 | struct date today={23,11,2021}; 21 | int myArray[]={1,2,3,4,5}; 22 | struct date *pointerDate=NULL; 23 | char *myString="Hello, C."; 24 | 25 | pointerDate=(struct date *) malloc(sizeof(struct date)); 26 | pointerDate->day=25; 27 | pointerDate->month=12; 28 | pointerDate->year=2021; 29 | 30 | printf("The variable 'today' is %d - %d - %d.\n", today.day,today.month,today.year); 31 | printf("The variable behind 'pointerDate' is %d - %d - %d.\n", pointerDate->day,pointerDate->month,(*pointerDate).year); 32 | 33 | 34 | today=incrementDay(today); 35 | printf("The variable 'today' after change is %d - %d - %d.\n", today.day,today.month,today.year); 36 | 37 | free(pointerDate); 38 | pointerDate=NULL; 39 | } -------------------------------------------------------------------------------- /Bit manipulations/Binary numbers and bits/challenge_convert_binary_numbers_to_decimal.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | int convert_binary_to_decimal(long long binaryNumber); 9 | 10 | int main(int argc, char **argv) 11 | { 12 | long long inputBinaryNumber; 13 | int resultDecimalNumber; 14 | 15 | printf("Please enter the binary number you wish to convert to decimal: \t"); 16 | scanf("%lld",&inputBinaryNumber); 17 | 18 | resultDecimalNumber=convert_binary_to_decimal(inputBinaryNumber); 19 | 20 | puts(" "); 21 | printf("The binary number ==> %lld converts to the following decimal number ==> %ld .\n",inputBinaryNumber,resultDecimalNumber); 22 | 23 | return 0; 24 | } 25 | 26 | 27 | int convert_binary_to_decimal(long long binaryNumber) 28 | { 29 | int decimalNumber=0; 30 | int i=0; 31 | int remainder=0; 32 | 33 | while(binaryNumber!=0) 34 | { 35 | remainder=binaryNumber %10; 36 | binaryNumber=binaryNumber/10; 37 | decimalNumber+=remainder*pow(2,i); 38 | ++i; 39 | } 40 | 41 | return decimalNumber; 42 | } 43 | -------------------------------------------------------------------------------- /Input and Output/Formatting functions/using_fprintf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* =============================================== 5 | Notes: 6 | - int fprintf(FILE *filepointer,const char * characterformat,...) 7 | - fprintf() goes from File Print Format 8 | ================================================= */ 9 | 10 | int main(void) 11 | { 12 | FILE *file_pointer=NULL; 13 | char buffer[100]; 14 | 15 | file_pointer=fopen("thefile.txt","r+"); 16 | 17 | if(!file_pointer) 18 | { 19 | puts("Error when opening the file."); 20 | exit(-1); 21 | } 22 | 23 | for(int i=0;i<10;i++) 24 | { 25 | fprintf(file_pointer,"The calculus is %d.\n",i); 26 | } 27 | 28 | fclose(file_pointer); 29 | 30 | puts("============== reading the content of the file now ========="); 31 | 32 | file_pointer=fopen("thefile.txt","r"); 33 | 34 | if(!file_pointer) 35 | { 36 | puts("Error when opening the file."); 37 | exit(-1); 38 | } 39 | 40 | while(!feof(file_pointer)) 41 | { 42 | fgets(buffer,100,file_pointer); 43 | printf("%s",buffer); 44 | } 45 | 46 | fclose(file_pointer); 47 | 48 | return 0; 49 | } -------------------------------------------------------------------------------- /Threads/Thread Synchronisation Concepts/using_mutex_example_1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | pthread_mutex_t this_lock; 7 | int global_variable=43; 8 | 9 | 10 | void *do_process(void *argument) 11 | { 12 | puts("In this new thread I am using the global variable."); 13 | 14 | pthread_mutex_lock(&this_lock); 15 | int i=0; 16 | 17 | global_variable++; 18 | 19 | while(i<10) 20 | { 21 | printf("%d\t .....\n",global_variable); 22 | sleep(1); 23 | i++; 24 | } 25 | 26 | puts("....completing the work now."); 27 | 28 | pthread_mutex_unlock(&this_lock); 29 | 30 | return NULL; 31 | } 32 | 33 | int main(int argc, char **argv) 34 | { 35 | int error; 36 | pthread_t thread1, thread2; 37 | 38 | int result=pthread_mutex_init(&this_lock,NULL); 39 | 40 | if(result) 41 | { 42 | printf("Error when creating mutex.\n"); 43 | exit(1); 44 | } 45 | 46 | pthread_create(&thread1,NULL,do_process,NULL); 47 | pthread_create(&thread2,NULL,do_process,NULL); 48 | 49 | pthread_join(thread1,NULL); 50 | pthread_join(thread2,NULL); 51 | 52 | 53 | 54 | 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /Unions/Defining a union/example_how_to_define_a_union.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* ======================================================================================== 4 | Tips and tricks information: At this stage only the new data type is defined. There is no memory allocated for the union type. 5 | The memory gets allocated once objects associated with the union are created 6 | ======================================================================================== */ 7 | union car 8 | { 9 | int i_value; //size of float is 4 bytes 10 | float f_value; // size of float is 4 bytes 11 | char brand[20]; // size if 20 * 1byte = 20 bytes 12 | }; 13 | 14 | int main(void) 15 | { 16 | /* ======================================== 17 | Tips and tricks: once the objects are created, memory gets allocated for that object. 18 | ========================================== */ 19 | 20 | union car dacia, renault, *audi; 21 | 22 | printf("The size occupied in memory by the object of type union is represented by the largest member of the union as all members of the union share a common memory space at a given time ====> %zd bytes. \n",sizeof(dacia)); //should display 20 bytes 23 | 24 | 25 | 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /Shared Libraries and Shared Objects/Creating a static library/myDemo/myDemo.cbp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 42 | 43 | -------------------------------------------------------------------------------- /Advanced Pointers/Use Cases/example_when_passing_function_argument_pointer_as_copy_2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void foo(int *thePointer) //this function passes a copy of the pointer, not the pointer itself 5 | { 6 | int a=43; 7 | thePointer=&a; //this is a copy of the initial pointer and these properties stay here in the function. 8 | puts("==== this is from inside the function ====="); 9 | printf("The address of the pointer variable is %p, the value stored in the pointer is %p and the value it points to is %d.\n",&thePointer,thePointer,*thePointer); 10 | puts("==== function stops here ====="); 11 | } 12 | 13 | 14 | int main(void) 15 | { 16 | int *ptr=NULL; 17 | ptr=(int *) malloc(sizeof(int)); 18 | 19 | printf("The memory address where the ptr variable is stored is %p.\n",&ptr); 20 | printf("The value stored in ptr is %p.\n",ptr); 21 | printf("The value stored at the memory location stored in the variable ptr is %d\n",*ptr); 22 | 23 | puts("==== execute function with a copy of the pointer as parameter ======"); 24 | 25 | *ptr=10; 26 | foo(ptr); 27 | 28 | printf("The memory address where the ptr variable is stored is %p.\n",&ptr); 29 | printf("The value stored in ptr is %p.\n",ptr); 30 | printf("The value stored at the memory location stored in the variable ptr is %d\n",*ptr); //since the function used a copy of the pointer, the original pointer ptr still points to 10 31 | 32 | 33 | return 0; 34 | } -------------------------------------------------------------------------------- /Shared Libraries and Shared Objects/Creating a static library/myStaticLibrary/myStaticLibrary.cbp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 45 | 46 | -------------------------------------------------------------------------------- /Threads/Common Thread Functions/stack_management_functions.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | pthread_attr_t thread_attributes; 8 | 9 | void *thread_function(void *arguments) 10 | { 11 | long thread_ID; 12 | size_t my_stack_size; 13 | 14 | pthread_attr_getstacksize(&thread_attributes,&my_stack_size); 15 | 16 | thread_ID=(long) arguments; 17 | 18 | printf("In the thread %lu: \t the stack size is %li Bytes",thread_ID,my_stack_size); 19 | 20 | pthread_exit(NULL); 21 | } 22 | 23 | int main(int argc, char **argv) 24 | { 25 | pthread_t thread_id; 26 | size_t new_stacksize; 27 | int myVar=43; 28 | 29 | pthread_attr_init(&thread_attributes); 30 | pthread_attr_getstacksize(&thread_attributes,&new_stacksize); 31 | 32 | printf("Default stack size is %lu.\n",new_stacksize); 33 | 34 | new_stacksize=8000000; 35 | printf("The new thread needs to have the following stack size %lu.\n",new_stacksize); 36 | 37 | pthread_attr_setstacksize(&thread_attributes,new_stacksize); 38 | printf("At this point, we are creating a new thread with the stacksize of %lu Bytes.\n",new_stacksize); 39 | 40 | int result=pthread_create(&thread_id,&thread_attributes,thread_function,(void *) myVar); 41 | 42 | if(result) 43 | { 44 | printf("Error when creating the thread with %d.\n", errno); 45 | exit(-1); 46 | } 47 | 48 | pthread_join(thread_id,NULL); 49 | 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /Macros/Predefined Macros/using_predefined_macros.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* ============================================================== 4 | Good practice: Feel free to use the following predefined macros 5 | __FILE__ : stands for the name (string %s) of the current file 6 | __LINE__ : stands for the line number (integer %d) where it executes 7 | __func__ : stands for the name of the function in whose body it is placed (string %s) 8 | __DATE__ : stands for the date when the file was compiled last time (string %s) 9 | __TIME__ : stands for the time when the file was compiled last time (string %s) 10 | __STDC__ : stands for 1 is standard compiler implementation was used , or 0 if a non standard compiler was used (integer %d) 11 | ================================================================= */ 12 | 13 | void my_personal_function(void) 14 | { 15 | printf("This is the name of the function being executed at this moment \"%s\" \n",__func__); 16 | } 17 | 18 | 19 | int main(void) 20 | { 21 | printf("This file was last time compiled on %s and at time %s.\n",__DATE__,__TIME__); 22 | 23 | printf("The name of this file is %s and currently it runs the line %d.\n",__FILE__,__LINE__); 24 | 25 | if(__STDC__==1) 26 | { 27 | puts("Great news. This program was compiled using a compiler compliant with ISO C"); 28 | } 29 | else 30 | { 31 | puts("Bad luck. This program was compiled using a compiler non-ISO compliant version of C"); 32 | } 33 | 34 | my_personal_function(); 35 | 36 | return 0; 37 | } -------------------------------------------------------------------------------- /Storage classes/Static variables/Using static variables in functions/using_static_variables.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* ========================================================== 4 | Notes: the static keyword has different meanings depending where it is applied 5 | 1. if the static keyword is applied to a local variable , then that variable retains its value every time the function is re-appealed. The variable does not initialize 6 | 2. it the static keyword is applied to a global variable, then that variable can not be seen outside of the current file where the global variable is defined into 7 | 3. if the static keyword is applied to a function, then that function can only be used within that file 8 | ============================================================= */ 9 | 10 | 11 | foo() 12 | { 13 | static int myStaticVariable=0; 14 | int myLocalVariable=0; //this is an auto variable, but the 'auto' keyword is implicit, there is no necessarily need to add it 15 | 16 | printf("The value of the static variable is : %d , and the value of the auto variable is %d. \n", myStaticVariable, myLocalVariable); 17 | 18 | myStaticVariable++; 19 | myLocalVariable++; //the auto variable gets reset anytime when the function exits. 20 | 21 | printf("The 2nd value of the static variable is : %d , and the value of the auto variable is %d. \n", myStaticVariable, myLocalVariable); 22 | puts("============================================"); 23 | 24 | } 25 | 26 | 27 | 28 | 29 | int main(void) 30 | { 31 | for(int i=0;i<=10;i++) 32 | { 33 | foo(); 34 | } 35 | 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /Threads/Thread Synchronisation Concepts/an_example_of_deadlock.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | pthread_mutex_t mutex1,mutex2; 8 | 9 | void *thread_function1(void *argument) 10 | { 11 | puts("The work started in with resource 1"); 12 | 13 | pthread_mutex_lock(&mutex1); 14 | sleep(2); 15 | 16 | puts("Trying to get resource no.2"); 17 | 18 | pthread_mutex_lock(&mutex2); 19 | puts("Resource 2 was acquired."); 20 | 21 | pthread_mutex_unlock(&mutex2); 22 | puts("Resource 2 unlocked "); 23 | 24 | pthread_mutex_unlock(&mutex1); 25 | puts("Resource 1 unlocked."); 26 | 27 | pthread_exit(NULL); 28 | } 29 | 30 | void *thread_function2(void *argument) 31 | { 32 | puts("The work has started with the resource 2"); 33 | pthread_mutex_lock(&mutex2); 34 | sleep(2); 35 | 36 | puts("Trying to get resource 1"); 37 | pthread_mutex_lock(&mutex1); 38 | puts("Resource 1 was acquired"); 39 | 40 | pthread_mutex_unlock(&mutex1); 41 | puts("Resource 1 was freed."); 42 | 43 | pthread_mutex_unlock(&mutex2); 44 | puts("Resource 2 was freed"); 45 | 46 | pthread_exit(NULL); 47 | } 48 | 49 | 50 | 51 | int main(int argc, char **argv) 52 | { 53 | pthread_mutex_init(&mutex1,NULL); 54 | pthread_mutex_init(&mutex2,NULL); 55 | 56 | pthread_t thread1, thread2; 57 | 58 | pthread_create(&thread1,NULL,thread_function1,NULL); 59 | pthread_create(&thread2,NULL,thread_function2,NULL); 60 | 61 | 62 | pthread_join(thread1,NULL); 63 | pthread_join(thread2,NULL); 64 | 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /Advanced Pointers/conceptual_example_2_pointer_to_pointer.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) 4 | { 5 | int **double_pointer=NULL; 6 | 7 | int var1=10; 8 | int var2=43; 9 | int var3=64; 10 | 11 | int *pVar1=&var1; 12 | int *pVar2=&var2; 13 | int *pVar3=&var3; 14 | 15 | double_pointer=&pVar1; 16 | 17 | printf("The memory address where \"double_pointer\" variable is stored is %p.\n",&double_pointer); 18 | printf("The value stored in the \"double pointer\" variable %p which is the memory address it points to %p.\n",double_pointer,&pVar1); 19 | printf("The value to which the \"double pointer\" points to is %p.\n", *double_pointer ); 20 | printf("The value derefenced of the \"double pointer\" variable is %d=%d.\n",**double_pointer,*pVar1); 21 | puts("--------------------------------"); 22 | 23 | *double_pointer=pVar2; //it means the double_pointer variable is dereferenced as pVar2, so to say the value it points to is pVar2. Hence since double_pointer=&pVar1 it means the pVar1 points to pVar2; 24 | 25 | printf("The value stored in the \"double pointer\" variable %p which is the memory address it points to %p.\n",double_pointer,&pVar1); 26 | printf("The value to which the \"double pointer\" points to is %p which is the memory address of where \"pVar2\".\n", *double_pointer ); 27 | printf("The value derefenced of the \"double pointer\" variable is %d=%d.\n",**double_pointer,*pVar2); 28 | 29 | puts("--------------------- from the points of view of variable \"pVar1\"------------------"); 30 | printf("The value stored in the variable \"pVar1\" is %p=%p.\n",pVar1,pVar2); 31 | printf("The value to which the variable \"pVar1\" points to is %d=%d.\n",*pVar1,*pVar2); 32 | 33 | return 0; 34 | } -------------------------------------------------------------------------------- /Threads/Thread Synchronisation Concepts/solution_to_resolve_a_deadlock.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | pthread_mutex_t mutex1,mutex2; 8 | 9 | void *thread_function1(void *argument) 10 | { 11 | puts("The work started in with resource 1"); 12 | 13 | pthread_mutex_lock(&mutex1); 14 | sleep(2); 15 | 16 | puts("Trying to get resource no.2"); 17 | 18 | while(pthread_mutex_trylock(&mutex2)) 19 | { 20 | pthread_mutex_unlock(&mutex1); 21 | sleep(2); 22 | pthread_mutex_lock(&mutex1); 23 | } 24 | 25 | 26 | puts("Resource 2 was acquired."); 27 | 28 | pthread_mutex_unlock(&mutex2); 29 | puts("Resource 2 unlocked "); 30 | 31 | pthread_mutex_unlock(&mutex1); 32 | puts("Resource 1 unlocked."); 33 | 34 | pthread_exit(NULL); 35 | } 36 | 37 | void *thread_function2(void *argument) 38 | { 39 | puts("The work has started with the resource 2"); 40 | pthread_mutex_lock(&mutex2); 41 | sleep(2); 42 | 43 | puts("Trying to get resource 1"); 44 | pthread_mutex_lock(&mutex1); 45 | puts("Resource 1 was acquired"); 46 | 47 | pthread_mutex_unlock(&mutex1); 48 | puts("Resource 1 was freed."); 49 | 50 | pthread_mutex_unlock(&mutex2); 51 | puts("Resource 2 was freed"); 52 | 53 | pthread_exit(NULL); 54 | } 55 | 56 | 57 | 58 | int main(int argc, char **argv) 59 | { 60 | pthread_mutex_init(&mutex1,NULL); 61 | pthread_mutex_init(&mutex2,NULL); 62 | 63 | pthread_t thread1, thread2; 64 | 65 | pthread_create(&thread1,NULL,thread_function1,NULL); 66 | pthread_create(&thread2,NULL,thread_function2,NULL); 67 | 68 | 69 | pthread_join(thread1,NULL); 70 | pthread_join(thread2,NULL); 71 | 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /Advanced Pointers/Use Cases/example_when_passing_function_argument_pointer_as_copy.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | void foo(int *thePointer) //this function passes a copy of the pointer, not the pointer itself 5 | { 6 | int a=43; 7 | thePointer=&a; //this is a copy of the initial pointer and these properties stay here in the function. 8 | printf("The address of the pointer variable is %p, the value stored in the pointer is %p and the value it points to is %d.\n",&thePointer,thePointer,*thePointer); 9 | } 10 | 11 | int main(void) 12 | { 13 | int x=65; 14 | 15 | int *pp=NULL; 16 | int *p=NULL; 17 | 18 | 19 | p=&x; 20 | pp=&p; 21 | 22 | printf("The memory address where pp is stored is %p.\n",&pp); 23 | printf("The memory address where p is stored is %p.\n",&p); 24 | 25 | puts("=================================================="); 26 | 27 | printf("The value stored in the pp variable is %p.\n",pp); 28 | printf("The value stored in the p variable is %p.\n",p); 29 | 30 | puts("=================================================="); 31 | 32 | printf("The value stored at the location where the pp variable points to is %p=%p. \n",*pp,p); 33 | printf("The value stored at the location where the p variable points to is %d.\n",*p); 34 | //printf("The dereferenced variable of **pp is %d.\n",(int *) **pp); 35 | 36 | puts("=================================================="); 37 | puts("=================================================="); 38 | 39 | foo(p); //function foo() takes as argument a copy of the pointer p. Locally it is assigned to a certain memory address ,but the actual p pointer does not change 40 | printf("The memory address where p is stored is %p.\n",&p); 41 | printf("The value stored in the p variable is %p.\n",p); 42 | printf("The value stored at the location where the p variable points to is %d.\n",*p); 43 | 44 | return 0; 45 | } -------------------------------------------------------------------------------- /Advanced Pointers/conceptual_example_3_pointer_to_pointer.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) 4 | { 5 | int **pointer_to_pointer=NULL; 6 | 7 | int var1=10; 8 | int var2=43; 9 | int var3=66; 10 | 11 | int *pVar1=&var1; 12 | int *pVar2=&var2; 13 | int *pVar3=&var3; 14 | 15 | pointer_to_pointer=&pVar1; 16 | 17 | printf("The memory address where the \"pointer_to_pointer\" variable is stored is %p.\n",&pointer_to_pointer); 18 | printf("The value of the \"pointer_to_pointer\" variable which is the same value as the memory address where the variable \"pVar1\" is stored is %p=%p.\n",pointer_to_pointer,&pVar1); 19 | printf("The dereferenced \"pointer_to_pointer\" variable so to say the value that exists where \"pointer_to_pointer\" variable is pointing to is %p=%p.\n",*pointer_to_pointer,pVar1); 20 | printf("The completely derefenced value of the \"pointer_to_pointer\" variable which the value where the intermediate pointer variable points to is %d=%d.\n",**pointer_to_pointer,*pVar1); 21 | puts("============================="); 22 | 23 | *pointer_to_pointer=&var3; 24 | printf("The memory address where the \"pointer_to_pointer\" variable is stored is %p.\n",&pointer_to_pointer); //these remain the same as above 25 | printf("The value of the \"pointer_to_pointer\" variable which is the same value as the memory address where the variable \"pVar1\" is stored is %p=%p.\n",pointer_to_pointer,&pVar1); //these remain the same as above 26 | printf("The dereferenced \"pointer_to_pointer\" variable so to say the value that exists where \"pointer_to_pointer\" variable is pointing to is %p=%p.\n",*pointer_to_pointer,pVar1); //due to the change that affects the pointer_to_pointer, the intermediat pointer variable is affected too 27 | printf("The completely derefenced value of the \"pointer_to_pointer\" variable which the value where the intermediate pointer variable points to is %d=%d.\n",**pointer_to_pointer,*pVar1); 28 | } -------------------------------------------------------------------------------- /Interprocess Communication/testing_continuing_after_raising_sigstop_from_command_line.txt: -------------------------------------------------------------------------------- 1 | georgeca@georgeca-VirtualBox:~/Desktop$ kill -s SIGCONT 3051 2 | georgeca@georgeca-VirtualBox:~/Desktop$ LS 3 | LS: command not found 4 | georgeca@georgeca-VirtualBox:~/Desktop$ ls 5 | client KLS.desktop LOG_20220302_2 tcp_client_ip_143 6 | eclipse LOG_20220302 log_2312_01_noerror token.txt 7 | georgeca@georgeca-VirtualBox:~/Desktop$ cd .. 8 | georgeca@georgeca-VirtualBox:~$ ls 9 | Compilers Downloads my_sandbox Qt Videos 10 | Desktop eclipse-workspace Pictures snap Workspace 11 | Documents Music Public Templates 12 | georgeca@georgeca-VirtualBox:~$ cd my_sandbox/ 13 | georgeca@georgeca-VirtualBox:~/my_sandbox$ ls 14 | Advanced-C-Programming-Course 15 | Explore-C-Libraries 16 | Inter-Process-Communication-in-C 17 | kls_main_process_with_threads_OLD 18 | LibraryDesigning 19 | Linux-System-Programming-tools-and-techniques 20 | Master-the-C-Language 21 | MultithreadingBible 22 | georgeca@georgeca-VirtualBox:~/my_sandbox$ cd Advanced-C-Programming-Course/ 23 | georgeca@georgeca-VirtualBox:~/my_sandbox/Advanced-C-Programming-Course$ ls 24 | 2021-11-04_16-18-29.png README.md 25 | 'Advanced Control Flow' 'Shared Libraries and Shared Objects' 26 | 'Advanced Data Types' 'Storage classes' 27 | 'Advanced Debugging and Analysis' 'The Preprocessor' 28 | 'Advanced Pointers' 'Type Qualifiers' 29 | 'Bit manipulations' Unions 30 | 'Input and Output' 'Useful C libraries' 31 | 'Interprocess Communication' 'Working with extern variables' 32 | Macros 'Working with Larger Programs' 33 | georgeca@georgeca-VirtualBox:~/my_sandbox/Advanced-C-Programming-Course$ cd In 34 | Input and Output/ Interprocess Communication/ 35 | georgeca@georgeca-VirtualBox:~/my_sandbox/Advanced-C-Programming-Course$ cd Interprocess\ Communication/ 36 | georgeca@georgeca-VirtualBox:~/my_sandbox/Advanced-C-Programming-Course/Interprocess Communication$ ls 37 | get_process_id listing_the_signals_from_command_line.txt raising_a_signal.c 38 | get_process_id.c raising_a_signal 39 | georgeca@georgeca-VirtualBox:~/my_sandbox/Advanced-C-Programming-Course/Interprocess Communication$ ./raising_a_signal 40 | The process id is 3110. We will test raising a SIGSTOP signal for this process and starting over this process from command line. 41 | 42 | georgeca@georgeca-VirtualBox:~/my_sandbox/Advanced-C-Programming-Course/Interprocess Communication$ kill -s SIGCONT 3110 43 | georgeca@georgeca-VirtualBox:~/my_sandbox/Advanced-C-Programming-Course/Interprocess Communication$ I am back after starting from the keyboard 44 | -------------------------------------------------------------------------------- /Networking/creating_a_client_socket.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | short create_socket() 10 | { 11 | short this_socket=0; 12 | printf("Creating the file descriptor for the master socket.\n"); 13 | 14 | this_socket=socket(AF_INET,SOCK_STREAM,0); 15 | 16 | return this_socket; 17 | } 18 | 19 | int connect_to_server(int socket_number) 20 | { 21 | int returned_value=-1; 22 | 23 | int server_port=2005; 24 | 25 | struct sockaddr_in remote_server={0}; 26 | remote_server.sin_family=AF_INET; 27 | remote_server.sin_addr.s_addr=inet_addr("127.0.0.1"); 28 | remote_server.sin_port=htons(server_port); 29 | 30 | returned_value=connect(socket_number,(struct sockaddr *) &remote_server, sizeof(remote_server)); 31 | 32 | return returned_value; 33 | } 34 | 35 | int send_to_server(int socket_number, char *request, short length_request) 36 | { 37 | int short_returned_value=-1; 38 | 39 | struct timeval tv; 40 | tv.tv_sec=20; //timeout 41 | tv.tv_usec=0; 42 | 43 | if(setsockopt(socket_number,SOL_SOCKET,SO_SNDTIMEO,(char *) &tv, sizeof(tv))<0) 44 | { 45 | puts("Timed out"); 46 | return -1; 47 | } 48 | 49 | short_returned_value=send(socket_number,request,length_request,0); 50 | return short_returned_value; 51 | } 52 | 53 | 54 | int receive_in_socket(int socket_number, char *response, short receive_size) 55 | { 56 | int returned_value=-1; 57 | struct timeval tv; 58 | tv.tv_sec=20; 59 | tv.tv_usec=0; 60 | 61 | if(setsockopt(socket_number,SOL_SOCKET,SO_RCVTIMEO, (char *)&tv, sizeof(tv))<0) 62 | { 63 | printf("Timed out.\n"); 64 | return -1; 65 | } 66 | 67 | 68 | returned_value=recv(socket_number,response,receive_size,0); 69 | printf("Response >> %s.\n",response); 70 | 71 | return returned_value; 72 | } 73 | 74 | 75 | int main(int argc, char **argv) 76 | { 77 | int thissocket=0, read_size=0; 78 | struct sockaddr_in remote_server; 79 | 80 | char sendtoServer[100]={0}; 81 | char server_reply[200]={0}; 82 | 83 | //Create the socket 84 | thissocket=create_socket(); 85 | 86 | if(thissocket==-1) 87 | { 88 | perror("Could not create socket."); 89 | exit(-1); 90 | } 91 | 92 | //Connect to the server 93 | if(connect_to_server(thissocket)<0) 94 | { 95 | perror("Error connecting to server."); 96 | return -1; 97 | } 98 | 99 | 100 | puts("Successfully connected to the server."); 101 | puts("Enter your message"); 102 | 103 | fgets(sendtoServer,100,stdin); 104 | 105 | //send data to server 106 | send_to_server(thissocket,sendtoServer,sizeof(sendtoServer)); 107 | 108 | 109 | //receive data from server 110 | read_size=receive_in_socket(thissocket,server_reply,200); 111 | printf("The response from server is >>> %s.\n",server_reply); 112 | 113 | close(thissocket); 114 | 115 | return 0; 116 | } 117 | -------------------------------------------------------------------------------- /Networking/creating_a_server_socket.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | 11 | short create_the_socket(void) 12 | { 13 | short this_socket=-1; 14 | puts("Now I am creating the socket to establish the communication. aka a virtual endpoint needed that communication happen"); 15 | 16 | this_socket=socket(AF_INET,SOCK_STREAM,0); 17 | 18 | if(this_socket<0) 19 | { 20 | perror("Error during socket creation"); 21 | } 22 | 23 | return this_socket; 24 | } 25 | 26 | int bind_the_socket(int this_socket) 27 | { 28 | int returned_value=-1; 29 | 30 | int port_number=2005; 31 | 32 | struct sockaddr_in my_sockaddr={0}; //initialize all its members to 0 33 | 34 | my_sockaddr.sin_family=AF_INET; 35 | my_sockaddr.sin_addr.s_addr=htonl(INADDR_ANY); //set to a random address 36 | my_sockaddr.sin_port=htons(port_number); //use the port set above 37 | 38 | returned_value=bind(this_socket,(struct sockaddr_in *) &my_sockaddr,sizeof(my_sockaddr)); 39 | 40 | return returned_value; 41 | } 42 | 43 | 44 | int main(int argc, char **argv) 45 | { 46 | int socket_description=0, client_socket=0, clientLength=0; 47 | struct sockaddr_in client; 48 | char client_message[200]={0}; 49 | char message[200]={0}; 50 | 51 | const char *pMessage="hello from Jason's server"; 52 | 53 | //Create a socket 54 | socket_description=create_the_socket(); 55 | 56 | if(socket_description==-1) 57 | { 58 | puts("Could not create the socket."); 59 | return 1; 60 | } 61 | 62 | puts("Socket was created successfully."); 63 | 64 | //Bind the socket=attach the socket to an address and a port 65 | if(bind_the_socket(socket_description)<0) 66 | { 67 | perror("Could not bind the socket."); 68 | return 1; 69 | } 70 | 71 | puts("Bind was done"); 72 | 73 | //Listen 74 | listen(socket_description,3); 75 | 76 | //Accepts incoming connections 77 | while(1) 78 | { 79 | printf("Waiting for incoming connections.\n"); 80 | clientLength=sizeof(struct sockaddr_in); 81 | 82 | //accept connections from incoming connections 83 | client_socket=accept(socket_description,(struct sockaddr_in *) &client, (socklen_t *) &clientLength); 84 | 85 | if(client_socket<0) 86 | { 87 | perror("Could not accept"); 88 | return 1; 89 | } 90 | 91 | printf("Connection accepted."); 92 | 93 | //initializing the buffers to send and receive messages 94 | 95 | memset(client_message,'\0',sizeof(client_message)); 96 | memset(message,'\0',sizeof(message)); 97 | 98 | //receive from the client 99 | 100 | if(recv(client_socket,client_message,200,0)<0) 101 | { 102 | perror("Receive failed"); 103 | exit(1); 104 | } 105 | 106 | printf("Client replies with >> %s .\n",client_message); 107 | 108 | //validation of the received message 109 | if(strcmp(pMessage,client_message)==0) 110 | { 111 | strcpy(message,"Hi,there. You are the chosen one."); 112 | } 113 | else 114 | { 115 | strcpy(message,"No shit. It is an invalid message."); 116 | } 117 | 118 | //send the message back to the client 119 | if(send(client_socket,message,strlen(message),0)<0) 120 | { 121 | perror("Error when sending message from server."); 122 | return 1; 123 | } 124 | 125 | 126 | close(client_socket); 127 | sleep(1); 128 | 129 | } 130 | 131 | return 0; 132 | } 133 | -------------------------------------------------------------------------------- /Data Structures/Linked Lists/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | //self referential stucture 6 | typedef node 7 | { 8 | char element; 9 | struct node *nextElement; 10 | } node_t; 11 | 12 | typedef node_t* listNodePointers; 13 | 14 | 15 | //define functions prototypes 16 | void insert(listNodePointers *head, char value); 17 | void insertAtEnd(listNodePointers *head, char value); 18 | void insertAtBeginning(listNodePointers *head, char value); 19 | char delete(listNodePointers *head, char value); 20 | void deleteAtBeginning(listNodePointers *head); 21 | int isEmpty(listNodePointers head); 22 | void printList(listNodePointers currentPointer); 23 | 24 | 25 | int main(void) 26 | { 27 | listNodePointers head=NULL; //Initialize the linked list. It is initially empty 28 | int user_choice=0; 29 | char item='\0'; //character entered by the user 30 | 31 | //display the user menu 32 | printf("Enter your choice: \n" 33 | " 1 to insert an element to the list in alphabetical order. \n" 34 | " 2 to insert an element at the end of the list . \n" 35 | " 3 to insert an element at the beginning of the list. \n" 36 | " 4. to delete an element from the list. \n" 37 | " 5. to delete an element from the beginning of the list. \n" 38 | " 6. to end. \n"); 39 | 40 | //read input from the user 41 | printf(":: "); 42 | scanf("%d", &user_choice); 43 | 44 | //loop through the operations until end request is entered by the user 45 | while(user_choice!=6) 46 | { 47 | switch(user_choice) 48 | { 49 | case (1): 50 | printf("Enter character to insert: \n"); 51 | scanf("%c",&item); 52 | insert(&head,item); 53 | printList(head); 54 | break; 55 | case(2): 56 | printf("Enter character to insert: \n"); 57 | scanf("%c",&item); 58 | insertAtEnd(&head,item); 59 | printList(head); 60 | break; 61 | case(3): 62 | printf("Enter character to insert \n"); 63 | scanf("%c", item); 64 | insertAtBeginning(&head,item); 65 | printList(head); 66 | break; 67 | case(4): 68 | if(!isEmpty(head)) 69 | { 70 | printf("Enter character to delete: \n"); 71 | scanf("%c",item); 72 | 73 | if(delete(&head, item)) 74 | { 75 | printf("Character %c was found and it was deleted. \n",item); 76 | printList(head); 77 | } 78 | else 79 | { 80 | printf("The character you entered was not found in the linked list.\n"); 81 | } 82 | } 83 | else 84 | { 85 | printf("The list is empty. I can not delete anything. \n"); 86 | } 87 | break; 88 | case(5): 89 | if(!isEmpty(head)) 90 | { 91 | deleteAtBeginning(&head); 92 | printf("I have deleted the first character at the beginning of the list.\n"); 93 | } 94 | else 95 | { 96 | printf("The list is empty and I can not delete anything.\n"); 97 | } 98 | break; 99 | default: 100 | printf("Invalid choice. Enter 1..5 for valid choices.\n"); 101 | break; 102 | } 103 | 104 | printf("? "); 105 | scanf("%d",user_choice); 106 | } 107 | 108 | printf("End of run.\n"); 109 | 110 | 111 | return 0; 112 | } 113 | 114 | 115 | void insertAtBeginning(listNodePointers *head, char value) 116 | { 117 | listNodePointers new_node=malloc(size(node_t)); 118 | new_node->element=value; 119 | new_node->nextElement=*head; 120 | *head=new_node; 121 | } 122 | 123 | void insertAtEnd(listNodePointers *head, char value) 124 | { 125 | listNodePointers current=*head; 126 | 127 | if(current!=NULL) //Not empty list, not at the end of the list 128 | { 129 | //traverse to the end of the list, last element of the list is NULL 130 | while(current->nextElement!=NULL) 131 | { 132 | current=current->nextElement; 133 | } 134 | 135 | //at this point we are at the end of the list, because the nextElement is NULL. We will add a new item to the list now 136 | current->nextElement=malloc(sizeof(node_t)); 137 | 138 | //Adding the value to the new last element and setting its element after it to NULL 139 | current->nextElement->element=value; 140 | current->nextElement->nextElement=NULL; 141 | } 142 | else 143 | { 144 | //In this case either the list is empty, there is no head. First element of the list is the head. OR we are already at the end of the list 145 | current=malloc(sizeof(node_t)); 146 | 147 | current->element=value; 148 | current->nextElement=NULL; 149 | *head=current; 150 | } 151 | 152 | 153 | } 154 | --------------------------------------------------------------------------------