C Basic Syntax Cheatsheet

16 min read

Table of Contents
- Basic Program Structure
- Data Types
- Variables & Constants
- Operators
- Control Structures
- Functions
- Arrays
- Pointers
- Strings
- Structures & Unions
- Input/Output
- Memory Management
- 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.