C Basic Syntax Cheatsheet

Anni HuangAnni Huang
16 min read

Table of Contents

  1. Basic Program Structure
  2. Data Types
  3. Variables & Constants
  4. Operators
  5. Control Structures
  6. Functions
  7. Arrays
  8. Pointers
  9. Strings
  10. Structures & Unions
  11. Input/Output
  12. Memory Management
  13. Preprocessor

Basic Program Structure

#include <stdio.h>      // Include standard I/O library
#include <stdlib.h>     // Include standard library

int main() {            // Main function - program entry point
    printf("Hello, World!\n");
    return 0;           // Return 0 for successful execution
}

// Alternative main with command line arguments
int main(int argc, char *argv[]) {
    printf("Program name: %s\n", argv[0]);
    printf("Number of arguments: %d\n", argc);
    return 0;
}

Comments

// Single line comment

/* 
   Multi-line comment
   Can span multiple lines
*/

Data Types

Basic Data Types

// Integer types
char c = 'A';                    // 1 byte, -128 to 127
unsigned char uc = 255;          // 1 byte, 0 to 255
short s = 32767;                 // 2 bytes, -32,768 to 32,767
unsigned short us = 65535;       // 2 bytes, 0 to 65,535
int i = 2147483647;              // 4 bytes, -2^31 to 2^31-1
unsigned int ui = 4294967295U;   // 4 bytes, 0 to 2^32-1
long l = 2147483647L;            // 4/8 bytes (platform dependent)
unsigned long ul = 4294967295UL; // 4/8 bytes
long long ll = 9223372036854775807LL;  // 8 bytes (C99)

// Floating point types
float f = 3.14f;                 // 4 bytes, ~6 decimal digits
double d = 3.141592653589793;    // 8 bytes, ~15 decimal digits
long double ld = 3.141592653589793L; // 8/10/16 bytes (platform dependent)

// Boolean (C99)
#include <stdbool.h>
bool flag = true;                // true or false
bool flag2 = false;

Type Sizes

#include <stdio.h>

int main() {
    printf("char: %zu bytes\n", sizeof(char));
    printf("int: %zu bytes\n", sizeof(int));
    printf("float: %zu bytes\n", sizeof(float));
    printf("double: %zu bytes\n", sizeof(double));
    printf("pointer: %zu bytes\n", sizeof(void*));
    return 0;
}

Variables & Constants

Variable Declaration

int x;                    // Declaration
int y = 10;              // Declaration with initialization
int a = 5, b = 10, c;    // Multiple variables

// Type qualifiers
const int MAX_SIZE = 100;        // Cannot be modified
volatile int sensor_data;        // Value may change unexpectedly
static int counter = 0;          // Retains value between function calls
register int fast_var;          // Hint to store in CPU register

Storage Classes

// Global variables
int global_var = 10;            // External linkage
static int file_scope_var = 20; // Internal linkage

int main() {
    // Local variables
    int local_var = 30;         // Automatic storage
    static int persistent = 0;   // Retains value between calls

    {
        int block_var = 40;     // Block scope
    }
    // block_var not accessible here

    return 0;
}

Constants

#define PI 3.14159              // Preprocessor constant (avoid spaces around =)
#define MAX_BUFFER 1024

const int BUFFER_SIZE = 512;    // Read-only variable
const char* const message = "Hello"; // Constant pointer to constant data

// Enumeration constants
enum Colors {
    RED,      // 0
    GREEN,    // 1
    BLUE      // 2
};

enum Status {
    SUCCESS = 1,
    FAILURE = -1,
    PENDING = 0
};

Operators

Arithmetic Operators

int a = 10, b = 3;

int sum = a + b;           // Addition: 13
int diff = a - b;          // Subtraction: 7
int product = a * b;       // Multiplication: 30
int quotient = a / b;      // Division: 3 (integer division)
int remainder = a % b;     // Modulus: 1

// Compound assignment
a += 5;                    // a = a + 5
a -= 3;                    // a = a - 3
a *= 2;                    // a = a * 2
a /= 4;                    // a = a / 4
a %= 3;                    // a = a % 3

Increment/Decrement

int x = 5;
++x;                       // Pre-increment: x becomes 6, returns 6
x++;                       // Post-increment: returns 6, then x becomes 7
--x;                       // Pre-decrement: x becomes 6, returns 6
x--;                       // Post-decrement: returns 6, then x becomes 5

Comparison Operators

int a = 5, b = 10;

int equal = (a == b);         // Equal to: 0 (false)
int not_equal = (a != b);     // Not equal to: 1 (true)
int less = (a < b);           // Less than: 1 (true)
int less_eq = (a <= b);       // Less than or equal: 1 (true)
int greater = (a > b);        // Greater than: 0 (false)
int greater_eq = (a >= b);    // Greater than or equal: 0 (false)

Logical Operators

int p = 1, q = 0;  // 1 = true, 0 = false

int and_result = p && q;      // Logical AND: 0 (false)
int or_result = p || q;       // Logical OR: 1 (true)
int not_result = !p;          // Logical NOT: 0 (false)

Bitwise Operators

int a = 5;    // Binary: 101
int b = 3;    // Binary: 011

int and_op = a & b;           // Bitwise AND: 1 (001)
int or_op = a | b;            // Bitwise OR: 7 (111)
int xor_op = a ^ b;           // Bitwise XOR: 6 (110)
int not_op = ~a;              // Bitwise NOT: -6
int left_shift = a << 1;      // Left shift: 10 (1010)
int right_shift = a >> 1;     // Right shift: 2 (10)

Other Operators

int x = 10;
int* ptr = &x;                // Address-of operator
int value = *ptr;             // Dereference operator
int size = sizeof(int);       // Size operator
int result = (x > 5) ? 1 : 0; // Ternary operator

Control Structures

If-Else Statements

int score = 85;

if (score >= 90) {
    printf("Grade A\n");
} else if (score >= 80) {
    printf("Grade B\n");
} else if (score >= 70) {
    printf("Grade C\n");
} else {
    printf("Grade F\n");
}

// Ternary operator
char* result = (score >= 60) ? "Pass" : "Fail";

Switch Statement

int choice = 2;

switch (choice) {
    case 1:
        printf("Option 1 selected\n");
        break;
    case 2:
        printf("Option 2 selected\n");
        break;
    case 3:
        printf("Option 3 selected\n");
        break;
    default:
        printf("Invalid choice\n");
        break;
}

Loops

For Loop

// Traditional for loop
for (int i = 0; i < 10; i++) {
    printf("%d ", i);
}

// Infinite loop
for (;;) {
    // Loop forever
    break; // Use break to exit
}

// Multiple variables
for (int i = 0, j = 10; i < j; i++, j--) {
    printf("i=%d, j=%d\n", i, j);
}

While Loop

int count = 0;
while (count < 5) {
    printf("%d ", count);
    count++;
}

Do-While Loop

int num;
do {
    printf("Enter a positive number: ");
    scanf("%d", &num);
} while (num <= 0);

Loop Control

for (int i = 0; i < 10; i++) {
    if (i == 3) {
        continue;    // Skip rest of this iteration
    }
    if (i == 7) {
        break;       // Exit the loop
    }
    printf("%d ", i);
}

Goto Statement (Generally Avoided)

int main() {
    int i = 0;

    loop_start:
    if (i < 5) {
        printf("%d ", i);
        i++;
        goto loop_start;
    }

    return 0;
}

Functions

Function Declaration and Definition

// Function declarations (prototypes)
int add(int a, int b);
void print_message(void);
double calculate_area(double radius);

// Function definitions
int add(int a, int b) {
    return a + b;
}

void print_message(void) {
    printf("Hello from function!\n");
}

double calculate_area(double radius) {
    return 3.14159 * radius * radius;
}

int main() {
    int sum = add(5, 3);
    print_message();
    double area = calculate_area(2.5);
    return 0;
}

Function Parameters

// Pass by value
void func1(int x) {
    x = 10;  // Only local copy is modified
}

// Pass by pointer (simulates pass by reference)
void func2(int* x) {
    *x = 10;  // Original variable is modified
}

// Array parameter (always passed by reference)
void func3(int arr[], int size) {
    arr[0] = 100;  // Modifies original array
}

// Alternative array syntax
void func4(int* arr, int size) {
    arr[0] = 100;  // Same as above
}

Variable Arguments (Variadic Functions)

#include <stdarg.h>

int sum(int count, ...) {
    va_list args;
    va_start(args, count);

    int total = 0;
    for (int i = 0; i < count; i++) {
        total += va_arg(args, int);
    }

    va_end(args);
    return total;
}

int main() {
    int result = sum(3, 10, 20, 30);  // Returns 60
    return 0;
}

Function Pointers

int add(int a, int b) {
    return a + b;
}

int multiply(int a, int b) {
    return a * b;
}

int main() {
    // Function pointer declaration
    int (*operation)(int, int);

    operation = add;
    int sum = operation(5, 3);        // Calls add function

    operation = multiply;
    int product = operation(5, 3);    // Calls multiply function

    return 0;
}

Arrays

One-Dimensional Arrays

// Declaration and initialization
int arr1[5];                           // Uninitialized array
int arr2[5] = {1, 2, 3, 4, 5};        // Initialized array
int arr3[] = {1, 2, 3};               // Size inferred from initializer
int arr4[5] = {1, 2};                 // Partially initialized (rest are 0)
int arr5[5] = {0};                    // All elements initialized to 0

// Accessing elements
arr1[0] = 10;                         // Set first element
int first = arr2[0];                  // Get first element

// Array size
int size = sizeof(arr2) / sizeof(arr2[0]);

Multi-Dimensional Arrays

// 2D array
int matrix[3][4] = {
    {1, 2, 3, 4},
    {5, 6, 7, 8},
    {9, 10, 11, 12}
};

// Alternative initialization
int matrix2[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};

// Accessing 2D array elements
matrix[1][2] = 100;                   // Set element at row 1, column 2
int value = matrix[0][3];             // Get element at row 0, column 3

// 3D array
int cube[2][3][4];
cube[0][1][2] = 42;

Array and Function Interaction

// Array as function parameter
void print_array(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

// 2D array as parameter
void print_matrix(int rows, int cols, int matrix[rows][cols]) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            printf("%d ", matrix[i][j]);
        }
        printf("\n");
    }
}

Pointers

Basic Pointer Operations

int x = 42;
int* ptr = &x;              // Pointer to x
int** pptr = &ptr;          // Pointer to pointer

// Dereferencing
int value = *ptr;           // Get value pointed to (42)
*ptr = 100;                 // Change value through pointer (x becomes 100)

// Pointer arithmetic
int arr[] = {1, 2, 3, 4, 5};
int* p = arr;               // Points to first element (arr[0])
p++;                        // Points to second element (arr[1])
p += 2;                     // Points to fourth element (arr[3])
int diff = p - arr;         // Difference in elements (3)

// Null pointer
int* null_ptr = NULL;       // Null pointer
if (null_ptr != NULL) {
    // Safe to dereference
}

Pointer Arithmetic

int arr[] = {10, 20, 30, 40, 50};
int* ptr = arr;

printf("%d\n", *ptr);       // 10 (arr[0])
printf("%d\n", *(ptr + 1)); // 20 (arr[1])
printf("%d\n", *(ptr + 2)); // 30 (arr[2])

// Pointer subtraction
int* start = &arr[1];
int* end = &arr[4];
int distance = end - start;  // 3 elements apart

Pointers and Arrays

int arr[] = {1, 2, 3, 4, 5};

// These are equivalent
printf("%d\n", arr[2]);     // Array notation
printf("%d\n", *(arr + 2)); // Pointer notation

// Array name is a pointer to first element
int* ptr = arr;             // Same as ptr = &arr[0]

Dynamic Memory Allocation

#include <stdlib.h>

// Allocate memory for single integer
int* ptr = (int*)malloc(sizeof(int));
if (ptr != NULL) {
    *ptr = 42;
    free(ptr);              // Always free allocated memory
    ptr = NULL;             // Avoid dangling pointer
}

// Allocate memory for array
int* arr = (int*)malloc(10 * sizeof(int));
if (arr != NULL) {
    for (int i = 0; i < 10; i++) {
        arr[i] = i * i;
    }
    free(arr);
    arr = NULL;
}

// calloc - allocates and initializes to zero
int* zeros = (int*)calloc(5, sizeof(int));

// realloc - resize allocated memory
int* resized = (int*)realloc(arr, 20 * sizeof(int));

Strings

String Basics

#include <string.h>

// String initialization
char str1[] = "Hello";              // Array of characters
char str2[20] = "World";            // Fixed-size array
char* str3 = "Constant String";     // Pointer to string literal
char str4[] = {'H', 'i', '\0'};    // Manual null termination

// String length
int len = strlen(str1);             // 5 (doesn't count '\0')

String Functions

#include <string.h>

char dest[50];
char src[] = "Hello";

// String copy
strcpy(dest, src);                  // Copy src to dest
strncpy(dest, src, 10);            // Copy at most 10 characters

// String concatenation
strcat(dest, " World");            // Append " World" to dest
strncat(dest, "!", 1);             // Append at most 1 character

// String comparison
int result = strcmp(str1, str2);    // 0 if equal, <0 if str1 < str2, >0 if str1 > str2
int result2 = strncmp(str1, str2, 3); // Compare first 3 characters

// String search
char* pos = strchr(str1, 'l');     // Find first occurrence of 'l'
char* pos2 = strstr(str1, "ll");   // Find first occurrence of "ll"

String Input/Output

#include <stdio.h>

char name[50];

// String input (stops at whitespace)
printf("Enter your name: ");
scanf("%s", name);                  // No & needed for arrays

// String input (reads entire line)
printf("Enter a sentence: ");
fgets(name, sizeof(name), stdin);   // Safer than gets()

// Remove newline from fgets
name[strcspn(name, "\n")] = '\0';

// String output
printf("Hello, %s!\n", name);
puts(name);                         // Automatically adds newline

Structures & Unions

Structures

// Structure definition
struct Person {
    char name[50];
    int age;
    float height;
};

// Using typedef for convenience
typedef struct {
    int x;
    int y;
} Point;

int main() {
    // Structure initialization
    struct Person person1 = {"Alice", 25, 5.6};
    struct Person person2;

    Point p1 = {10, 20};
    Point p2;

    // Accessing structure members
    person2.age = 30;
    strcpy(person2.name, "Bob");
    person2.height = 6.0;

    // Pointer to structure
    struct Person* ptr = &person1;
    printf("Name: %s\n", ptr->name);   // Arrow operator
    printf("Age: %d\n", (*ptr).age);   // Equivalent to above

    return 0;
}

Nested Structures

struct Address {
    char street[100];
    char city[50];
    int zip_code;
};

struct Employee {
    char name[50];
    int id;
    struct Address address;
};

int main() {
    struct Employee emp;
    strcpy(emp.name, "John Doe");
    emp.id = 12345;
    strcpy(emp.address.street, "123 Main St");
    strcpy(emp.address.city, "Anytown");
    emp.address.zip_code = 12345;

    return 0;
}

Unions

// Union - members share the same memory location
union Data {
    int integer;
    float floating;
    char character;
};

int main() {
    union Data data;

    data.integer = 42;
    printf("Integer: %d\n", data.integer);

    data.floating = 3.14f;  // Overwrites integer value
    printf("Float: %.2f\n", data.floating);

    // Size of union is size of largest member
    printf("Union size: %zu\n", sizeof(union Data));

    return 0;
}

Enumerations

// Simple enumeration
enum Weekday {
    MONDAY,    // 0
    TUESDAY,   // 1
    WEDNESDAY, // 2
    THURSDAY,  // 3
    FRIDAY,    // 4
    SATURDAY,  // 5
    SUNDAY     // 6
};

// Enumeration with custom values
enum Status {
    SUCCESS = 1,
    FAILURE = -1,
    PENDING = 0
};

int main() {
    enum Weekday today = FRIDAY;
    enum Status result = SUCCESS;

    if (today == FRIDAY) {
        printf("Thank God it's Friday!\n");
    }

    return 0;
}

Input/Output

Standard I/O

#include <stdio.h>

int main() {
    int num;
    float price;
    char grade;
    char name[50];

    // Output
    printf("Enter a number: ");
    scanf("%d", &num);

    printf("Enter a price: ");
    scanf("%f", &price);

    printf("Enter a grade: ");
    scanf(" %c", &grade);          // Space before %c to skip whitespace

    printf("Enter your name: ");
    scanf("%s", name);             // No & for arrays

    // Formatted output
    printf("Number: %d\n", num);
    printf("Price: $%.2f\n", price);
    printf("Grade: %c\n", grade);
    printf("Name: %s\n", name);

    return 0;
}

File I/O

#include <stdio.h>

int main() {
    FILE* file;
    char buffer[100];

    // Writing to file
    file = fopen("example.txt", "w");
    if (file != NULL) {
        fprintf(file, "Hello, File!\n");
        fprintf(file, "Number: %d\n", 42);
        fclose(file);
    }

    // Reading from file
    file = fopen("example.txt", "r");
    if (file != NULL) {
        while (fgets(buffer, sizeof(buffer), file) != NULL) {
            printf("%s", buffer);
        }
        fclose(file);
    }

    // Binary file operations
    int numbers[] = {1, 2, 3, 4, 5};
    file = fopen("numbers.bin", "wb");
    if (file != NULL) {
        fwrite(numbers, sizeof(int), 5, file);
        fclose(file);
    }

    // Reading binary file
    int read_numbers[5];
    file = fopen("numbers.bin", "rb");
    if (file != NULL) {
        fread(read_numbers, sizeof(int), 5, file);
        fclose(file);
    }

    return 0;
}

File Modes

// Text mode
FILE* file1 = fopen("file.txt", "r");   // Read only
FILE* file2 = fopen("file.txt", "w");   // Write only (truncates file)
FILE* file3 = fopen("file.txt", "a");   // Append only
FILE* file4 = fopen("file.txt", "r+");  // Read and write
FILE* file5 = fopen("file.txt", "w+");  // Read and write (truncates)
FILE* file6 = fopen("file.txt", "a+");  // Read and append

// Binary mode (add 'b')
FILE* bin1 = fopen("file.bin", "rb");   // Read binary
FILE* bin2 = fopen("file.bin", "wb");   // Write binary

Memory Management

Stack vs Heap

#include <stdlib.h>

void stack_example() {
    int local_var = 42;        // Stack allocation (automatic)
    int array[100];            // Stack allocation
    // Memory automatically freed when function exits
}

void heap_example() {
    // Heap allocation (manual)
    int* ptr = (int*)malloc(sizeof(int));
    int* arr = (int*)malloc(100 * sizeof(int));

    if (ptr != NULL && arr != NULL) {
        *ptr = 42;
        arr[0] = 10;

        // Must manually free
        free(ptr);
        free(arr);
        ptr = NULL;    // Avoid dangling pointers
        arr = NULL;
    }
}

Memory Functions

#include <stdlib.h>
#include <string.h>

int main() {
    // malloc - allocate uninitialized memory
    int* ptr1 = (int*)malloc(10 * sizeof(int));

    // calloc - allocate zero-initialized memory
    int* ptr2 = (int*)calloc(10, sizeof(int));

    // realloc - resize allocated memory
    ptr1 = (int*)realloc(ptr1, 20 * sizeof(int));

    // memset - set memory to specific value
    memset(ptr1, 0, 20 * sizeof(int));

    // memcpy - copy memory
    memcpy(ptr2, ptr1, 10 * sizeof(int));

    // memmove - safe memory copy (handles overlap)
    memmove(ptr1 + 1, ptr1, 9 * sizeof(int));

    // memcmp - compare memory
    int result = memcmp(ptr1, ptr2, 10 * sizeof(int));

    free(ptr1);
    free(ptr2);

    return 0;
}

Preprocessor

Preprocessor Directives

#include <stdio.h>          // Include system header
#include "myheader.h"       // Include user header

#define PI 3.14159          // Simple macro
#define MAX(a, b) ((a) > (b) ? (a) : (b))  // Function-like macro
#define SQUARE(x) ((x) * (x))

// Conditional compilation
#define DEBUG 1

#ifdef DEBUG
    #define DBG_PRINT(x) printf(x)
#else
    #define DBG_PRINT(x)
#endif

#ifndef MYHEADER_H
#define MYHEADER_H
// Header content here
#endif

// Predefined macros
int main() {
    printf("File: %s\n", __FILE__);
    printf("Line: %d\n", __LINE__);
    printf("Date: %s\n", __DATE__);
    printf("Time: %s\n", __TIME__);
    printf("Function: %s\n", __func__);  // C99

    return 0;
}

Macro Best Practices

// Use parentheses to avoid precedence issues
#define MULTIPLY(a, b) ((a) * (b))

// Multi-line macros
#define SWAP(a, b) do { \
    typeof(a) temp = a; \
    a = b; \
    b = temp; \
} while(0)

// Stringification
#define STRINGIFY(x) #x
#define PRINT_VAR(var) printf(#var " = %d\n", var)

// Token pasting
#define CONCAT(a, b) a##b

int main() {
    int x = 10, y = 20;
    PRINT_VAR(x);           // Prints "x = 10"

    int CONCAT(my, var) = 42;  // Creates variable 'myvar'

    return 0;
}

Common Patterns & Best Practices

Error Handling

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

int divide(int a, int b, int* result) {
    if (b == 0) {
        return -1;  // Error code
    }
    *result = a / b;
    return 0;       // Success
}

int main() {
    FILE* file = fopen("nonexistent.txt", "r");
    if (file == NULL) {
        printf("Error opening file: %s\n", strerror(errno));
        return 1;
    }

    int result;
    if (divide(10, 0, &result) != 0) {
        printf("Division by zero error\n");
        return 1;
    }

    return 0;
}

Safe String Handling

#include <stdio.h>
#include <string.h>

void safe_string_copy(char* dest, const char* src, size_t dest_size) {
    if (dest_size > 0) {
        strncpy(dest, src, dest_size - 1);
        dest[dest_size - 1] = '\0';  // Ensure null termination
    }
}

int main() {
    char buffer[10];
    safe_string_copy(buffer, "Hello, World!", sizeof(buffer));
    printf("%s\n", buffer);  // Safely truncated

    return 0;
}

Generic Programming with Macros

#define DECLARE_ARRAY(type) \
    typedef struct { \
        type* data; \
        size_t size; \
        size_t capacity; \
    } type##_array_t;

#define ARRAY_INIT(arr, initial_capacity) do { \
    (arr)->data = malloc((initial_capacity) * sizeof(*(arr)->data)); \
    (arr)->size = 0; \
    (arr)->capacity = (initial_capacity); \
} while(0)

DECLARE_ARRAY(int)      // Creates int_array_t
DECLARE_ARRAY(double)   // Creates double_array_t

int main() {
    int_array_t int_arr;
    ARRAY_INIT(&int_arr, 10);

    // Use the array...

    free(int_arr.data);
    return 0;
}
0
Subscribe to my newsletter

Read articles from Anni Huang directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Anni Huang
Anni Huang

I am Anni HUANG, a software engineer with 3 years of experience in IDE development and Chatbot.