Introduction to Functions
Functions are the building blocks of C programs. They allow code reuse, modularity, and better organization. A function is a self-contained block of code that performs a specific task and can be called from other parts of the program.
Function Architecture Overview
Function Structure ├── Function Declaration (Prototype) │ ├── Return Type │ ├── Function Name │ └── Parameter List ├── Function Definition │ ├── Function Header │ ├── Local Variables │ ├── Function Body │ └── Return Statement └── Function Call ├── Arguments ├── Stack Frame └── Return Value
Basic Function Syntax
Function Declaration (Prototype)
return_type function_name(parameter_type1 parameter1, parameter_type2 parameter2, ...);
Function Definition
return_type function_name(parameter_type1 parameter1, parameter_type2 parameter2, ...) { // Function body // Local variables // Statements return value; // If return_type is not void } Simple Function Example
#include <stdio.h> // Function declaration int add(int a, int b); int main() { int x = 10, y = 20; int result; // Function call result = add(x, y); printf("%d + %d = %d\n", x, y, result); return 0; } // Function definition int add(int a, int b) { return a + b; } Output:
10 + 20 = 30
Types of Functions
1. Functions with Return Value and Parameters
#include <stdio.h> // Function that returns maximum of two numbers int max(int a, int b) { return (a > b) ? a : b; } int main() { int num1 = 45, num2 = 78; int maximum = max(num1, num2); printf("Maximum of %d and %d is %d\n", num1, num2, maximum); return 0; } 2. Functions with Return Value but No Parameters
#include <stdio.h> #include <stdlib.h> #include <time.h> // Function that returns a random number int getRandomNumber() { return rand() % 100; } int main() { srand(time(NULL)); // Seed random generator for (int i = 0; i < 5; i++) { printf("Random number %d: %d\n", i+1, getRandomNumber()); } return 0; } 3. Functions with No Return Value (void) but Parameters
#include <stdio.h> // Void function that prints a pattern void printPattern(int n, char symbol) { for (int i = 1; i <= n; i++) { for (int j = 1; j <= i; j++) { printf("%c ", symbol); } printf("\n"); } } int main() { printPattern(5, '*'); printf("\n"); printPattern(4, '#'); return 0; } Output:
* * * * * * * * * * * * * * * # # # # # # # # # #
4. Functions with No Return Value and No Parameters
#include <stdio.h> // Function that prints a welcome message void printWelcome() { printf("************************\n"); printf("* Welcome to My App *\n"); printf("************************\n"); } int main() { printWelcome(); printf("Main program continues...\n"); return 0; } Function Parameters
1. Pass by Value
#include <stdio.h> void modifyValue(int x) { printf("Inside function (before): x = %d\n", x); x = 100; // Modifies local copy only printf("Inside function (after): x = %d\n", x); } int main() { int num = 50; printf("Before function call: num = %d\n", num); modifyValue(num); printf("After function call: num = %d\n", num); return 0; } Output:
Before function call: num = 50 Inside function (before): x = 50 Inside function (after): x = 100 After function call: num = 50
2. Pass by Reference (using Pointers)
#include <stdio.h> void swap(int *a, int *b) { int temp = *a; *a = *b; *b = temp; printf("Inside swap: a = %d, b = %d\n", *a, *b); } int main() { int x = 10, y = 20; printf("Before swap: x = %d, y = %d\n", x, y); swap(&x, &y); printf("After swap: x = %d, y = %d\n", x, y); return 0; } Output:
Before swap: x = 10, y = 20 Inside swap: a = 20, b = 10 After swap: x = 20, y = 10
3. Passing Arrays to Functions
#include <stdio.h> // Method 1: Using array notation void printArray1(int arr[], int size) { printf("Array elements: "); for (int i = 0; i < size; i++) { printf("%d ", arr[i]); } printf("\n"); } // Method 2: Using pointer notation void printArray2(int *arr, int size) { printf("Array elements (pointer): "); for (int i = 0; i < size; i++) { printf("%d ", *(arr + i)); } printf("\n"); } // Modify array elements void doubleArray(int *arr, int size) { for (int i = 0; i < size; i++) { arr[i] *= 2; } } int main() { int numbers[] = {1, 2, 3, 4, 5}; int size = sizeof(numbers) / sizeof(numbers[0]); printArray1(numbers, size); printArray2(numbers, size); doubleArray(numbers, size); printf("After doubling: "); printArray1(numbers, size); return 0; } 4. Passing Strings to Functions
#include <stdio.h> #include <string.h> int countVowels(char str[]) { int count = 0; for (int i = 0; str[i] != '\0'; i++) { char c = tolower(str[i]); if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') { count++; } } return count; } void toUpperCase(char *str) { for (int i = 0; str[i] != '\0'; i++) { if (str[i] >= 'a' && str[i] <= 'z') { str[i] = str[i] - 32; } } } int main() { char text[] = "Hello World"; printf("Original: %s\n", text); printf("Vowel count: %d\n", countVowels(text)); toUpperCase(text); printf("Uppercase: %s\n", text); return 0; } Return Values
1. Returning Basic Types
#include <stdio.h> #include <math.h> int getSquare(int x) { return x * x; } float getAverage(float a, float b) { return (a + b) / 2.0; } char getGrade(int score) { if (score >= 90) return 'A'; else if (score >= 80) return 'B'; else if (score >= 70) return 'C'; else if (score >= 60) return 'D'; else return 'F'; } int main() { printf("Square of 5: %d\n", getSquare(5)); printf("Average of 10.5 and 20.5: %.2f\n", getAverage(10.5, 20.5)); printf("Grade for 85: %c\n", getGrade(85)); return 0; } 2. Returning Pointers
#include <stdio.h> #include <stdlib.h> // Return pointer to static array (DANGEROUS - don't do this in real code) int* getStaticArray() { static int arr[5] = {10, 20, 30, 40, 50}; return arr; // Returns pointer to static array } // Return pointer to dynamically allocated memory int* createArray(int size, int initialValue) { int *arr = (int*)malloc(size * sizeof(int)); if (arr != NULL) { for (int i = 0; i < size; i++) { arr[i] = initialValue; } } return arr; // Caller must free this memory } int main() { // Static array return int *staticArr = getStaticArray(); printf("Static array: "); for (int i = 0; i < 5; i++) { printf("%d ", staticArr[i]); } printf("\n"); // Dynamic array return int *dynamicArr = createArray(10, 5); if (dynamicArr != NULL) { printf("Dynamic array: "); for (int i = 0; i < 10; i++) { printf("%d ", dynamicArr[i]); } printf("\n"); free(dynamicArr); // Don't forget to free! } return 0; } 3. Returning Structures
#include <stdio.h> #include <string.h> typedef struct { char name[50]; int age; float salary; } Employee; Employee createEmployee(const char *name, int age, float salary) { Employee emp; strcpy(emp.name, name); emp.age = age; emp.salary = salary; return emp; } void printEmployee(Employee emp) { printf("Name: %s, Age: %d, Salary: %.2f\n", emp.name, emp.age, emp.salary); } int main() { Employee emp1 = createEmployee("John Doe", 30, 50000.0); Employee emp2 = createEmployee("Jane Smith", 28, 55000.0); printEmployee(emp1); printEmployee(emp2); return 0; } Function Scope and Lifetime
1. Local Variables
#include <stdio.h> void function1() { int x = 10; // Local to function1 printf("function1: x = %d\n", x); } void function2() { int x = 20; // Local to function2 (different from function1's x) printf("function2: x = %d\n", x); } int main() { int x = 5; // Local to main printf("main: x = %d\n", x); function1(); function2(); printf("main: x = %d\n", x); return 0; } 2. Static Variables
#include <stdio.h> void counter() { static int count = 0; // Initialized only once count++; printf("Count = %d\n", count); } int main() { printf("Static variable example:\n"); counter(); // Count = 1 counter(); // Count = 2 counter(); // Count = 3 counter(); // Count = 4 return 0; } 3. Global Variables
#include <stdio.h> // Global variable int globalCounter = 0; void incrementCounter() { globalCounter++; // Modifies global variable } void resetCounter() { globalCounter = 0; } void printCounter() { printf("Global counter: %d\n", globalCounter); } int main() { printCounter(); // 0 incrementCounter(); incrementCounter(); incrementCounter(); printCounter(); // 3 resetCounter(); printCounter(); // 0 return 0; } Recursive Functions
1. Factorial Using Recursion
#include <stdio.h> unsigned long long factorial(int n) { // Base case if (n == 0 || n == 1) { return 1; } // Recursive case return n * factorial(n - 1); } int main() { for (int i = 0; i <= 10; i++) { printf("%d! = %llu\n", i, factorial(i)); } return 0; } Output:
0! = 1 1! = 1 2! = 2 3! = 6 4! = 24 5! = 120 6! = 720 7! = 5040 8! = 40320 9! = 362880 10! = 3628800
2. Fibonacci Series Using Recursion
#include <stdio.h> int fibonacci(int n) { if (n <= 1) { return n; } return fibonacci(n - 1) + fibonacci(n - 2); } int main() { int terms = 10; printf("Fibonacci series (%d terms):\n", terms); for (int i = 0; i < terms; i++) { printf("%d ", fibonacci(i)); } printf("\n"); return 0; } 3. Tower of Hanoi
#include <stdio.h> void towerOfHanoi(int n, char from, char to, char aux) { if (n == 1) { printf("Move disk 1 from %c to %c\n", from, to); return; } towerOfHanoi(n - 1, from, aux, to); printf("Move disk %d from %c to %c\n", n, from, to); towerOfHanoi(n - 1, aux, to, from); } int main() { int disks = 3; printf("Tower of Hanoi with %d disks:\n", disks); towerOfHanoi(disks, 'A', 'C', 'B'); return 0; } Output:
Tower of Hanoi with 3 disks: Move disk 1 from A to C Move disk 2 from A to B Move disk 1 from C to B Move disk 3 from A to C Move disk 1 from B to A Move disk 2 from B to C Move disk 1 from A to C
Function Pointers
1. Basic Function Pointer
#include <stdio.h> int add(int a, int b) { return a + b; } int subtract(int a, int b) { return a - b; } int multiply(int a, int b) { return a * b; } int divide(int a, int b) { if (b != 0) return a / b; return 0; } int main() { // Declare function pointer int (*operation)(int, int); int x = 20, y = 5; // Use function pointer operation = add; printf("Add: %d\n", operation(x, y)); operation = subtract; printf("Subtract: %d\n", operation(x, y)); operation = multiply; printf("Multiply: %d\n", operation(x, y)); operation = divide; printf("Divide: %d\n", operation(x, y)); return 0; } 2. Array of Function Pointers
#include <stdio.h> void printHello() { printf("Hello"); } void printWorld() { printf("World"); } void printExclamation() { printf("!"); } void printNewLine() { printf("\n"); } int main() { // Array of function pointers void (*functions[])() = { printHello, printWorld, printExclamation, printNewLine }; // Call functions using array for (int i = 0; i < 4; i++) { functions[i](); } return 0; } 3. Function Pointers as Parameters
#include <stdio.h> // Function that takes another function as parameter void processArray(int arr[], int size, int (*operation)(int)) { for (int i = 0; i < size; i++) { arr[i] = operation(arr[i]); } } int square(int x) { return x * x; } int doubleIt(int x) { return x * 2; } int increment(int x) { return x + 1; } void printArray(int arr[], int size, const char *name) { printf("%s: ", name); for (int i = 0; i < size; i++) { printf("%d ", arr[i]); } printf("\n"); } int main() { int numbers[] = {1, 2, 3, 4, 5}; int size = sizeof(numbers) / sizeof(numbers[0]); printArray(numbers, size, "Original"); processArray(numbers, size, square); printArray(numbers, size, "After square"); processArray(numbers, size, doubleIt); printArray(numbers, size, "After double"); processArray(numbers, size, increment); printArray(numbers, size, "After increment"); return 0; } Inline Functions (C99)
#include <stdio.h> // Inline function definition inline int max(int a, int b) { return (a > b) ? a : b; } // Static inline - common in header files static inline int min(int a, int b) { return (a < b) ? a : b; } int main() { int x = 10, y = 20; printf("max(%d, %d) = %d\n", x, y, max(x, y)); printf("min(%d, %d) = %d\n", x, y, min(x, y)); return 0; } Variadic Functions
1. Variable Number of Arguments
#include <stdio.h> #include <stdarg.h> // Function that sums variable number of integers int sum(int count, ...) { va_list args; int total = 0; va_start(args, count); for (int i = 0; i < count; i++) { total += va_arg(args, int); } va_end(args); return total; } // Function that finds maximum among variable arguments int maxOf(int count, ...) { va_list args; int max, current; va_start(args, count); max = va_arg(args, int); // First argument for (int i = 1; i < count; i++) { current = va_arg(args, int); if (current > max) { max = current; } } va_end(args); return max; } int main() { printf("Sum of 3, 5, 7: %d\n", sum(3, 3, 5, 7)); printf("Sum of 1, 2, 3, 4, 5: %d\n", sum(5, 1, 2, 3, 4, 5)); printf("Max of 10, 20, 15: %d\n", maxOf(3, 10, 20, 15)); printf("Max of 100, 50, 75, 200, 150: %d\n", maxOf(5, 100, 50, 75, 200, 150)); return 0; } 2. printf-style Variadic Function
#include <stdio.h> #include <stdarg.h> void myPrintf(const char *format, ...) { va_list args; va_start(args, format); vprintf(format, args); // Use vprintf for variadic printing va_end(args); } int main() { myPrintf("Hello %s, your score is %d and grade is %c\n", "Alice", 95, 'A'); myPrintf("Value: %f, Hex: %x\n", 3.14159, 255); return 0; } Advanced Function Examples
1. Calculator Program
#include <stdio.h> #include <stdlib.h> // Function prototypes float add(float a, float b) { return a + b; } float subtract(float a, float b) { return a - b; } float multiply(float a, float b) { return a * b; } float divide(float a, float b) { return (b != 0) ? a / b : 0; } float power(float base, int exp) { float result = 1; for (int i = 0; i < abs(exp); i++) { result *= base; } return (exp >= 0) ? result : 1 / result; } // Function pointer array typedef struct { char symbol; float (*func)(float, float); char *name; } Operation; int main() { Operation ops[] = { {'+', add, "Addition"}, {'-', subtract, "Subtraction"}, {'*', multiply, "Multiplication"}, {'/', divide, "Division"}, {'^', (float (*)(float, float))power, "Power"} }; int choice; float a, b; printf("=== Calculator ===\n"); printf("Operations:\n"); for (int i = 0; i < 5; i++) { printf("%d. %s (%c)\n", i+1, ops[i].name, ops[i].symbol); } printf("Enter choice (1-5): "); scanf("%d", &choice); if (choice >= 1 && choice <= 5) { printf("Enter two numbers: "); scanf("%f %f", &a, &b); float result; if (choice == 5) { result = ((float (*)(float, int))ops[4].func)(a, (int)b); } else { result = ops[choice-1].func(a, b); } printf("Result: %.2f\n", result); } else { printf("Invalid choice\n"); } return 0; } 2. Sorting with Function Pointers
#include <stdio.h> #include <string.h> #include <stdlib.h> // Comparison functions int compareAscending(const void *a, const void *b) { return (*(int*)a - *(int*)b); } int compareDescending(const void *a, const void *b) { return (*(int*)b - *(int*)a); } int compareAbsolute(const void *a, const void *b) { return abs(*(int*)a) - abs(*(int*)b); } void printArray(int arr[], int size, const char *message) { printf("%s: ", message); for (int i = 0; i < size; i++) { printf("%d ", arr[i]); } printf("\n"); } int main() { int numbers[] = {5, -3, 10, -8, 2, -1, 7}; int size = sizeof(numbers) / sizeof(numbers[0]); printArray(numbers, size, "Original"); // Sort ascending int arr1[7]; memcpy(arr1, numbers, sizeof(numbers)); qsort(arr1, size, sizeof(int), compareAscending); printArray(arr1, size, "Ascending"); // Sort descending int arr2[7]; memcpy(arr2, numbers, sizeof(numbers)); qsort(arr2, size, sizeof(int), compareDescending); printArray(arr2, size, "Descending"); // Sort by absolute value int arr3[7]; memcpy(arr3, numbers, sizeof(numbers)); qsort(arr3, size, sizeof(int), compareAbsolute); printArray(arr3, size, "By absolute value"); return 0; } 3. Memoization for Performance
#include <stdio.h> #define MAX 100 // Memoized Fibonacci unsigned long long fibMemo(int n, unsigned long long memo[]) { if (memo[n] != 0) { return memo[n]; } if (n <= 1) { return n; } memo[n] = fibMemo(n-1, memo) + fibMemo(n-2, memo); return memo[n]; } // Regular recursive Fibonacci (inefficient) unsigned long long fibRecursive(int n) { if (n <= 1) return n; return fibRecursive(n-1) + fibRecursive(n-2); } int main() { unsigned long long memo[MAX] = {0}; printf("Memoized Fibonacci:\n"); for (int i = 0; i <= 40; i+=5) { printf("fib(%d) = %llu\n", i, fibMemo(i, memo)); } printf("\nPerformance comparison (fib(40)):\n"); clock_t start = clock(); unsigned long long result1 = fibMemo(40, memo); clock_t end = clock(); printf("Memoized: %llu (time: %ld ticks)\n", result1, end - start); start = clock(); unsigned long long result2 = fibRecursive(40); end = clock(); printf("Recursive: %llu (time: %ld ticks)\n", result2, end - start); return 0; } Common Pitfalls and Best Practices
1. Missing Function Prototypes
// BAD - no prototype int main() { int result = add(5, 3); // Compiler assumes add returns int // May cause issues if add returns something else return 0; } int add(int a, int b) { return a + b; } // GOOD - with prototype int add(int a, int b); // Prototype int main() { int result = add(5, 3); return 0; } int add(int a, int b) { return a + b; } 2. Returning Address of Local Variable
#include <stdio.h> // BAD - returning address of local variable int* badFunction() { int x = 10; return &x; // x is destroyed when function ends } // GOOD - static or dynamic allocation int* goodFunction() { static int x = 10; // Static - persists return &x; } int* betterFunction() { int *x = malloc(sizeof(int)); *x = 10; return x; // Caller must free } int main() { // This is undefined behavior // int *p = badFunction(); int *p1 = goodFunction(); printf("Static: %d\n", *p1); int *p2 = betterFunction(); printf("Dynamic: %d\n", *p2); free(p2); return 0; } 3. Not Checking for NULL
#include <stdio.h> #include <stdlib.h> void safeProcessArray(int *arr, int size) { if (arr == NULL) { printf("Error: NULL array passed\n"); return; } for (int i = 0; i < size; i++) { arr[i] *= 2; } } int main() { int *arr = malloc(5 * sizeof(int)); if (arr == NULL) { printf("Memory allocation failed\n"); return 1; } for (int i = 0; i < 5; i++) { arr[i] = i; } safeProcessArray(arr, 5); // OK safeProcessArray(NULL, 5); // Handled gracefully free(arr); return 0; } 4. Parameter Order Consistency
#include <stdio.h> #include <string.h> // BAD - inconsistent parameter order void copyString1(char *dest, char *src) { strcpy(dest, src); } void copyString2(char *src, char *dest) { strcpy(dest, src); } // Confusing! // GOOD - consistent with standard library void stringCopy(char *dest, const char *src) { strcpy(dest, src); } int main() { char dest[50]; const char *src = "Hello"; // Standard library uses (dest, src) strcpy(dest, src); // Your functions should follow the same convention stringCopy(dest, src); return 0; } Function Organization Best Practices
Header File Example (functions.h)
#ifndef FUNCTIONS_H #define FUNCTIONS_H // Function prototypes int add(int a, int b); int subtract(int a, int b); int multiply(int a, int b); double divide(int a, int b); // Inline function static inline int max(int a, int b) { return (a > b) ? a : b; } // Constants #define PI 3.14159 #endif Implementation File (functions.c)
#include "functions.h" #include <stdio.h> int add(int a, int b) { return a + b; } int subtract(int a, int b) { return a - b; } int multiply(int a, int b) { return a * b; } double divide(int a, int b) { if (b == 0) { printf("Error: Division by zero\n"); return 0; } return (double)a / b; } Main Program (main.c)
#include <stdio.h> #include "functions.h" int main() { int x = 10, y = 5; printf("Add: %d\n", add(x, y)); printf("Subtract: %d\n", subtract(x, y)); printf("Multiply: %d\n", multiply(x, y)); printf("Divide: %.2f\n", divide(x, y)); printf("Max: %d\n", max(x, y)); return 0; } Performance Considerations
1. Function Call Overhead
#include <stdio.h> #include <time.h> // Inline function (suggested) static inline int squareInline(int x) { return x * x; } // Regular function int squareRegular(int x) { return x * x; } int main() { const int iterations = 10000000; int result = 0; clock_t start, end; // Test inline function start = clock(); for (int i = 0; i < iterations; i++) { result += squareInline(i % 100); } end = clock(); printf("Inline: %ld ticks\n", end - start); // Test regular function start = clock(); for (int i = 0; i < iterations; i++) { result += squareRegular(i % 100); } end = clock(); printf("Regular: %ld ticks\n", end - start); return 0; } 2. Function Inlining Trade-offs
// For small, frequently called functions static inline int min(int a, int b) { return (a < b) ? a : b; } // For larger functions, let compiler decide int complexCalculation(int a, int b, int c) { // Complex logic here return (a * b) + (b * c) + (c * a); } Conclusion
Key Takeaways
- Functions promote code reuse and modularity
- Function prototypes are essential for type checking
- Parameters can be passed by value or reference
- Return values can be of any type
- Scope determines variable accessibility
- Recursion provides elegant solutions for certain problems
- Function pointers enable dynamic behavior
- Variadic functions handle variable arguments
Best Practices Summary
- Always declare function prototypes
- Use meaningful function names
- Keep functions focused (single responsibility)
- Validate parameters
- Document complex functions
- Consider inline for small, frequently called functions
- Free dynamically allocated memory
- Avoid global variables when possible
- Use const for parameters that shouldn't be modified
- Handle errors gracefully
When to Use Functions
- Code that's used multiple times
- Complex operations that need isolation
- Logical units that form a coherent task
- Algorithms that benefit from recursion
- Interface boundaries between modules
Functions are fundamental to C programming, enabling modular, maintainable, and reusable code. Mastery of functions is essential for writing professional-quality C programs.
Complete C Programming Guide + Compilers Collection
1. C srand() Function – Understanding Seed Initialization
https://macronepal.com/understanding-the-c-srand-function
Explains how srand() initializes the pseudo-random number generator in C by setting a seed value. Using the same seed produces the same sequence, while time(NULL) gives different results each run.
2. C rand() Function Mechanics and Limitations
https://macronepal.com/c-rand-function-mechanics-and-limitations
Explains how rand() generates pseudo-random numbers between 0 and RAND_MAX, its deterministic nature, and limitations for security use cases.
3. C log() Function
https://macronepal.com/c-log-function-2
Covers natural logarithm calculation using <math.h> and its applications.
4. Mastering Date and Time in C
https://macronepal.com/mastering-date-and-time-in-c
Explains <time.h> functions like time(), clock(), difftime(), and struct tm.
5. Mastering time_t Type in C
https://macronepal.com/mastering-the-c-time_t-type-for-time-management
Explains time representation as seconds since Unix epoch and conversion functions.
6. C exp() Function
https://macronepal.com/c-exp-function-mechanics-and-implementation
Explains exponential function exp(x) and its scientific applications.
7. C log() Function (Alternate Guide)
https://macronepal.com/c-log-function
Comparison of log() and log10() with usage examples.
8. C log10() Function
https://macronepal.com/mastering-the-log10-function-in-c
Explains base-10 logarithm for engineering and scientific applications.
9. C tan() Function
https://macronepal.com/understanding-the-c-tan-function
Explains tangent function and radian-based calculations.
10. Random Numbers in C (Secure vs Predictable)
https://macronepal.com/mastering-c-random-numbers-for-secure-and-predictable-applications
Explains difference between rand() and secure randomness methods.
11. Free Online C Compiler
https://macronepal.com/free-online-c-code-compiler-2
Browser-based compiler for testing C programs instantly.
C Functions, Arguments, Parameters & Flow
Mastering Functions in C – Complete Guide
https://macronepal.com/c/mastering-functions-in-c-a-complete-guide/
Covers function structure, modular programming, and real-world usage.
Function Arguments in C
https://macronepal.com/c-function-arguments/
Explains how arguments are passed and used in function calls.
Function Parameters in C
https://macronepal.com/c-function-parameters/
Explains defining inputs for functions and matching them with arguments.
Function Declarations in C
https://macronepal.com/c-function-declarations-syntax-rules-and-best-practices/
Covers prototypes, syntax rules, and best practices.
Function Calls in C
https://macronepal.com/understanding-function-calls-in-c-syntax-mechanics-and-best-practices/
Explains execution flow and parameter handling during function calls.
Void Functions in C
https://macronepal.com/understanding-void-functions-in-c-syntax-patterns-and-best-practices/
Explains functions that do not return values.
Return Values in C
https://macronepal.com/c-return-values-mechanics-types-and-best-practices/
Explains different return types and how functions return results.
Pass-by-Value in C
https://macronepal.com/aws/understanding-pass-by-value-in-c-mechanics-implications-and-best-practices/
Explains how copies of variables are passed into functions.
Pass-by-Reference in C
https://macronepal.com/c/understanding-pass-by-reference-in-c-pointers-semantics-and-safe-practices/
Explains using pointers to modify original variables.
C strstr() Function
https://macronepal.com/aws/c-strstr-function/
Explains substring search inside strings in C.
C Preprocessor & Macros
https://macronepal.com/mastering-c-variadic-macros-for-flexible-debugging/
https://macronepal.com/mastering-the-stdc-macro-in-c/
https://macronepal.com/c-time-macro-mechanics-and-usage/
https://macronepal.com/understanding-the-c-date-macro/
https://macronepal.com/c-file-type/
https://macronepal.com/mastering-c-line-macro-for-debugging-and-diagnostics/
https://macronepal.com/mastering-predefined-macros-in-c/
https://macronepal.com/c-error-directive-mechanics-and-usage/
https://macronepal.com/understanding-the-c-pragma-directive/
https://macronepal.com/c-include-directive/
C Structures, Memory, Scope & Linkage
https://macronepal.com/mastering-structures-in-c/
https://macronepal.com/c-structure-declaration-mechanics-and-usage/
https://macronepal.com/c-structure-initialization-mechanics-and-best-practices/
https://macronepal.com/mastering-c-structure-member-access-for-reliable-data-handling/
https://macronepal.com/c-nested-structures/
https://macronepal.com/mastering-arrays-of-structures-in-c/
https://macronepal.com/c-structure-pointers-mechanics-and-implementation/
https://macronepal.com/understanding-c-structure-parameter-passing-mechanics/
https://macronepal.com/mastering-c-returning-structures-for-efficient-data-flow/
https://macronepal.com/c-self-referential-structures/
https://macronepal.com/mastering-structure-alignment-in-c/
https://macronepal.com/c-structure-padding-mechanics-and-optimization/
https://macronepal.com/understanding-c-flexible-array-members-mechanics-and-usage/
https://macronepal.com/mastering-c-anonymous-structures-for-flattened-data-layouts/
https://macronepal.com/c-unions/
https://macronepal.com/mastering-c-name-mangling-and-symbol-decoration/
https://macronepal.com/c-no-linkage-mechanics-and-scope-isolation/
https://macronepal.com/understanding-c-internal-linkage-mechanics-and-architecture/
C Scope, Storage Classes & Typedef
https://macronepal.com/mastering-function-prototype-scope-in-c/
https://macronepal.com/c-function-scope-mechanics-and-visibility/
https://macronepal.com/understanding-c-file-scope-mechanics-and-architecture/
https://macronepal.com/mastering-c-scope-rules-for-predictable-name-resolution/
https://macronepal.com/c-scope-rules/
https://macronepal.com/mastering-c-register-storage-class-for-historical-context-and-modern-alternatives/
https://macronepal.com/mastering-_thread_local-in-c/
https://macronepal.com/c-extern-storage-class-mechanics-and-usage/
https://macronepal.com/understanding-the-c-static-storage-class-mechanics-and-usage/
https://macronepal.com/c-auto-storage-class/
https://macronepal.com/c-typedef-with-pointers/
Extra Articles
https://macronepal.com/13757-2/
https://macronepal.com/13748-2/
https://macronepal.com/13747-2/
https://macronepal.com/13746-2/
https://macronepal.com/13745-2/
https://macronepal.com/13708-2/
https://macronepal.com/13707-2/
https://macronepal.com/13702-2/
Online Compilers
https://macronepal.com/free-html-online-code-compiler/
https://macronepal.com/free-online-python-code-compiler/
https://macronepal.com/free-online-python2-code-compiler/
https://macronepal.com/free-online-java-code-compiler/
https://macronepal.com/free-online-javascript-code-compiler/
https://macronepal.com/free-online-node-js-code-compiler/
https://macronepal.com/free-online-c-code-compiler/
https://macronepal.com/free-online-c-code-compiler-2/
https://macronepal.com/free-online-c-code-compiler-3/
https://macronepal.com/free-online-php-code-compiler/
https://macronepal.com/free-online-ruby-code-compiler/
https://macronepal.com/free-online-perl-code-compiler/
https://macronepal.com/free-online-lua-code-compiler/
https://macronepal.com/free-online-tcl-code-compiler/
https://macronepal.com/free-online-groovy-code-compiler/
https://macronepal.com/free-online-j-shell-code-compiler/
https://macronepal.com/free-online-haskell-code-compiler/
https://macronepal.com/free-online-scala-code-compiler/
https://macronepal.com/free-online-common-lisp-code-compiler/
https://macronepal.com/free-online-d-code-compiler/
https://macronepal.com/free-online-ada-code-compiler/
https://macronepal.com/free-erlang-code-compiler/
https://macronepal.com/free-online-assembly-code-compiler/
