Program Structure and Flow
Before writing any code, let's understand how a C program is organized. Every C program follows a specific structure, and understanding this structure is the first step to becoming a confident C programmer!
What is Program Structure?
Program structure refers to the organized way code is arranged in a C file. It includes the order of declarations, function definitions, and the logical flow of execution.
A well-structured program is easier to read, debug, and maintain. Good structure is a habit you should develop from day one!
Anatomy of a C Program
// 1. PREPROCESSOR DIRECTIVES (at the very top)
#include <stdio.h> // Include standard input/output library
#include <stdlib.h> // Include standard library
// 2. MACRO DEFINITIONS (constants and macros)
#define PI 3.14159
#define MAX_SIZE 100
// 3. GLOBAL VARIABLES (use sparingly!)
int globalCounter = 0;
// 4. FUNCTION PROTOTYPES (declarations)
void greetUser(char name[]);
int calculateSum(int a, int b);
// 5. MAIN FUNCTION (program entry point)
int main() {
// Your program starts executing here
printf("Hello, World!\n");
greetUser("Alice");
int result = calculateSum(5, 3);
printf("Sum: %d\n", result);
return 0; // Return 0 means success
}
// 6. FUNCTION DEFINITIONS
void greetUser(char name[]) {
printf("Welcome, %s!\n", name);
}
int calculateSum(int a, int b) {
return a + b;
}
How a C Program Flows
Preprocessing
Directives like #include are processed first. Headers are inserted into your code.
Compilation
Your code is checked for errors and converted to machine code.
Find main()
Execution ALWAYS starts at the main() function—no exceptions!
Execute
Code runs line by line from top to bottom inside main().
The main() Function: Your Program's Entry Point
Every C program must have exactly one main() function. This is where your program begins executing:
Standard main() Forms
// Form 1: Simple (most common)
int main() {
// your code
return 0;
}
// Form 2: With arguments
int main(int argc, char *argv[]) {
// argc = argument count
// argv = argument values
return 0;
}
Return Values
return 0;→ Program succeeded ✓return 1;→ General error occurredreturn EXIT_SUCCESS;→ Same as 0return EXIT_FAILURE;→ Same as non-zero
The OS uses this value to know if your program ran successfully.
main().
Preprocessor Directives
Before your C code is compiled, it goes through a preprocessor. This is like a
"preparation phase" that handles special instructions starting with the # symbol.
What is a Preprocessor Directive?
A preprocessor directive is a command that starts with # and is
processed before compilation begins. Directives are NOT C statements—they don't end with semicolons!
The preprocessor performs text substitution and file inclusion. It doesn't understand C syntax—it just manipulates text!
#include - Including Header Files
The #include directive copies the contents of another file into your program:
// System/Standard headers - use angle brackets < >
#include <stdio.h> // Standard Input/Output (printf, scanf)
#include <stdlib.h> // Standard Library (malloc, free, exit)
#include <string.h> // String functions (strlen, strcpy)
#include <math.h> // Math functions (sqrt, pow, sin)
#include <stdbool.h> // Boolean type (true, false) - C99
#include <limits.h> // Data type limits (INT_MAX, etc.)
// Your own headers - use double quotes " "
#include "myheader.h" // Looks in current directory first
#include "utils/helper.h" // Can include path
<header.h> - Angle Brackets
Searches in system/compiler directories. Use for standard library headers.
"header.h" - Double Quotes
Searches current directory first, then system directories. Use for your own headers.
#define - Creating Macros
The #define directive creates macros (text replacements):
// Simple constants
#define PI 3.14159
#define MAX_STUDENTS 100
#define GREETING "Hello, World!"
// Function-like macros (with parameters)
#define SQUARE(x) ((x) * (x))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define ABS(x) ((x) < 0 ? -(x) : (x))
// Multi-line macros (use backslash)
#define PRINT_DEBUG(msg) \
printf("DEBUG: %s\n", msg); \
printf("File: %s, Line: %d\n", __FILE__, __LINE__)
int main() {
float area = PI * 5 * 5; // PI becomes 3.14159
int sq = SQUARE(4); // Becomes ((4) * (4)) = 16
int bigger = MAX(10, 20); // Becomes ((10) > (20) ? (10) : (20)) = 20
printf("Area: %f\n", area);
printf("Square: %d\n", sq);
printf("Max: %d\n", bigger);
return 0;
}
SQUARE(2+3) would become
2+3*2+3 = 11 instead of ((2+3)*(2+3)) = 25.
Conditional Compilation
Include or exclude code based on conditions:
// Check if macro is defined
#define DEBUG // Comment this out to disable debug mode
#ifdef DEBUG
printf("Debug mode is ON\n");
printf("Variable x = %d\n", x);
#endif
// Check if macro is NOT defined
#ifndef PRODUCTION
printf("This is a development build\n");
#endif
// If-else conditions
#if MAX_SIZE > 100
printf("Large array mode\n");
#elif MAX_SIZE > 50
printf("Medium array mode\n");
#else
printf("Small array mode\n");
#endif
// Prevent multiple inclusion (header guards)
#ifndef MYHEADER_H
#define MYHEADER_H
// Header content goes here
#endif
Predefined Macros
C provides some built-in macros that are automatically available:
| Macro | Description | Example Output |
|---|---|---|
__FILE__ |
Current filename | "main.c" |
__LINE__ |
Current line number | 42 |
__DATE__ |
Compilation date | "Jan 24 2026" |
__TIME__ |
Compilation time | "14:30:00" |
__func__ |
Current function name (C99) | "main" |
#include <stdio.h>
int main() {
printf("This file: %s\n", __FILE__);
printf("This line: %d\n", __LINE__);
printf("Compiled on: %s at %s\n", __DATE__, __TIME__);
printf("Function: %s\n", __func__);
return 0;
}
Variables in C
If you're new to programming, don't worry—variables are one of the simplest concepts to understand! Think of your computer's memory like a giant warehouse with millions of storage boxes. A variable is simply one of those boxes with a label on it, where you can store a piece of information.
What is a Variable?
A variable is a named storage location in your computer's memory that holds a value.
You give it a name (like age or score), and the computer reserves a small
space in memory just for that data.
The word "variable" means "able to change" — because you can update the value stored in it anytime during your program!
Think of a variable like a labeled jar in your kitchen. The label says "Sugar" (that's the variable name), and inside you store actual sugar (that's the value). You can use the sugar, add more, or replace it entirely—but the jar stays the same.
Declaring Variables
To declare a variable in C, you specify the data type followed by the variable name:
// Syntax: data_type variable_name;
int age; // Declares an integer variable
float salary; // Declares a floating-point variable
char grade; // Declares a character variable
double precision; // Declares a double-precision variable
Initializing Variables
You can assign a value to a variable at the time of declaration (initialization):
// Declaration with initialization
int age = 25;
float salary = 50000.50;
char grade = 'A';
double pi = 3.14159265359;
// Multiple variables of the same type
int x = 10, y = 20, z = 30;
// Declaration first, assignment later
int score;
score = 95; // Assignment
Variable Naming Rules
Valid Names
age- lowercase lettersfirstName- camelCasetotal_score- underscore_private- starts with underscorecount1- letters and numbersMAX_VALUE- uppercase (constants)
Invalid Names
1count- cannot start with numberfirst-name- no hyphens allowedtotal score- no spacesint- reserved keywordfloat- reserved keywordmy@var- no special characters
studentAge instead of just a. Your future self will thank you!
Data Types in C
Now that you know what variables are, the next question is: what can you put inside them? That's where data types come in! A data type tells the computer what kind of information a variable will store—is it a number? A letter? A decimal value?
int, decimals go in
float, and letters go in char.
What is a Data Type?
A data type specifies what kind of value a variable can hold and how much memory space it needs. It tells the computer how to interpret the data stored in that memory location.
Why does this matter? Because 5 (a number)
and '5' (a character) are stored completely differently in memory!
Primary Data Types
| Data Type | Size (bytes) | Range | Example |
|---|---|---|---|
char |
1 | -128 to 127 or 0 to 255 | char letter = 'A'; |
int |
4 | -2,147,483,648 to 2,147,483,647 | int count = 100; |
float |
4 | 3.4E-38 to 3.4E+38 (6 decimal places) | float price = 19.99; |
double |
8 | 1.7E-308 to 1.7E+308 (15 decimal places) | double pi = 3.14159265; |
Type Modifiers
Modifiers change the range and size of data types:
signed / unsigned
Controls whether the type can hold negative values
unsigned int positive = 4000000000; // Only positive
signed int negative = -500; // Can be negative (default)
short / long
Controls the size of the data type
short int small = 32000; // 2 bytes
long int big = 2000000000L; // 4+ bytes
long long huge = 9000000000LL; // 8 bytes
Checking Size with sizeof()
Use the sizeof() operator to check the size of data types on your system:
#include <stdio.h>
int main() {
printf("Size of char: %zu bytes\n", sizeof(char)); // 1
printf("Size of int: %zu bytes\n", sizeof(int)); // 4
printf("Size of float: %zu bytes\n", sizeof(float)); // 4
printf("Size of double: %zu bytes\n", sizeof(double)); // 8
printf("Size of long: %zu bytes\n", sizeof(long)); // 4 or 8
printf("Size of long long: %zu bytes\n", sizeof(long long)); // 8
return 0;
}
sizeof() when size matters, especially for memory allocation.
Constants in C
Sometimes you have values that should never change in your program—like the value of Pi (3.14159) or the maximum number of players in a game. These are called constants. Once you set them, they're locked in place!
What is a Constant?
A constant is a value that is assigned once and cannot be changed during program execution. It's like a variable, but "locked" so nothing can modify it.
Why use constants? They make your code safer (no accidental changes), more readable (meaningful names instead of random numbers), and easier to maintain!
Using the const Keyword
The const keyword creates a read-only variable:
#include <stdio.h>
int main() {
const float PI = 3.14159;
const int MAX_STUDENTS = 100;
const char NEWLINE = '\n';
printf("PI = %f\n", PI);
printf("Max students: %d\n", MAX_STUDENTS);
// PI = 3.14; // ERROR: Cannot modify a const variable
return 0;
}
Using #define Preprocessor
The #define directive creates symbolic constants (macros):
#include <stdio.h>
#define PI 3.14159
#define MAX_SIZE 100
#define GREETING "Hello, World!"
#define SQUARE(x) ((x) * (x))
int main() {
float radius = 5.0;
float area = PI * radius * radius;
printf("Area: %f\n", area); // Area: 78.539750
printf("%s\n", GREETING); // Hello, World!
printf("Square of 4: %d\n", SQUARE(4)); // Square of 4: 16
return 0;
}
const vs #define
const
- Has a specific data type
- Occupies memory
- Can be used with debugger
- Scope follows normal rules
- Type-safe
#define
- No data type (text replacement)
- No memory allocated
- Replaced before compilation
- Global scope by default
- Can create macros with parameters
const for
type-safe constants and #define for simple macros and conditional compilation.
Output with printf()
How does your program "talk" to the user? Through output! The printf()
function is like your program's voice—it displays messages, numbers, and results on the screen
so users can see what's happening.
printf
stands for "print formatted". It's called "formatted" because you can
control exactly how things appear—like adding spaces, new lines, or showing numbers with specific decimal places.
What is printf()?
printf() is a built-in C function that sends formatted output to the screen (console).
It can display text, numbers, and the values of variables in a human-readable format.
Without printf(), your program would run silently with no visible results. It's one of the first functions every C programmer learns!
Basic Usage
#include <stdio.h>
int main() {
// Simple text output
printf("Hello, World!\n");
// Multiple printf statements
printf("Line 1\n");
printf("Line 2\n");
// Without newline (continues on same line)
printf("Part 1 ");
printf("Part 2\n"); // Output: Part 1 Part 2
return 0;
}
Printing Variables
Use format specifiers to print variable values:
#include <stdio.h>
int main() {
int age = 25;
float height = 5.9;
char grade = 'A';
char name[] = "Alice";
printf("Name: %s\n", name); // Name: Alice
printf("Age: %d years\n", age); // Age: 25 years
printf("Height: %.1f feet\n", height); // Height: 5.9 feet
printf("Grade: %c\n", grade); // Grade: A
// Multiple variables in one printf
printf("%s is %d years old\n", name, age); // Alice is 25 years old
return 0;
}
Escape Sequences
Special character combinations for formatting output:
| Escape Sequence | Description | Example Output |
|---|---|---|
\n |
Newline | Moves cursor to next line |
\t |
Tab | Horizontal tab space |
\\ |
Backslash | Prints a backslash \ |
\" |
Double quote | Prints a double quote " |
\' |
Single quote | Prints a single quote ' |
\r |
Carriage return | Moves cursor to beginning of line |
printf("Hello\tWorld\n"); // Hello World
printf("Line1\nLine2\n"); // Line1
// Line2
printf("She said \"Hi\"\n"); // She said "Hi"
printf("Path: C:\\Users\n"); // Path: C:\Users
Input with scanf()
Now let's learn how your program can "listen" to the user! The scanf() function
waits for the user to type something and then stores that input in a variable. It's how you
make interactive programs that respond to user input.
scanf
stands for "scan formatted". It "scans" what the user types and
converts it into the right format for your variable. Think of it as the opposite of printf()!
What is scanf()?
scanf() is a built-in C function that reads input from the keyboard and stores it
in variables. It pauses your program, waits for the user to type something and press Enter,
then saves that input.
The & symbol before variable names
in scanf() is crucial—it tells the function WHERE in memory to store the input. Forgetting it is
one of the most common beginner mistakes!
Basic Usage
Use the address-of operator (&) to pass variable addresses to scanf:
#include <stdio.h>
int main() {
int age;
float salary;
char grade;
// Reading an integer
printf("Enter your age: ");
scanf("%d", &age); // Note the & before variable name
// Reading a float
printf("Enter your salary: ");
scanf("%f", &salary);
// Reading a character
printf("Enter your grade: ");
scanf(" %c", &grade); // Space before %c to skip whitespace
printf("\nYou are %d years old\n", age);
printf("Salary: $%.2f\n", salary);
printf("Grade: %c\n", grade);
return 0;
}
Reading Multiple Values
#include <stdio.h>
int main() {
int day, month, year;
// Reading multiple integers at once
printf("Enter date (DD MM YYYY): ");
scanf("%d %d %d", &day, &month, &year);
printf("Date: %02d/%02d/%d\n", day, month, year);
// Reading with different separators
printf("Enter date (DD/MM/YYYY): ");
scanf("%d/%d/%d", &day, &month, &year);
printf("Date: %02d-%02d-%d\n", day, month, year);
return 0;
}
Reading Strings
#include <stdio.h>
int main() {
char name[50];
char city[50];
// Reading a single word (stops at whitespace)
printf("Enter your first name: ");
scanf("%s", name); // No & needed for arrays
// Reading a line with spaces using fgets (safer)
printf("Enter your city: ");
getchar(); // Clear newline from previous input
fgets(city, sizeof(city), stdin);
printf("Hello, %s from %s", name, city);
return 0;
}
&
before variable names in scanf() (except for arrays/strings). Forgetting it causes undefined behavior!
Format Specifiers
You've seen symbols like %d, %f, and %s in our examples.
These are called format specifiers—they're like placeholders that tell C
"put a value here" and "treat it as this type of data."
printf("I am %d years old", 25);, the
%d is a blank that gets filled with 25. The d tells C it's
a decimal (whole) number.
What is a Format Specifier?
A format specifier is a special code starting with % that tells
printf() and scanf() what type of data to expect and how to format it. Each data type has
its own specifier.
Using the wrong format specifier can cause
garbage output or crashes! Always match: %d for int, %f for float,
%c for char, %s for strings.
Common Format Specifiers
| Specifier | Data Type | Example | Output |
|---|---|---|---|
%d or %i |
int (signed decimal) | printf("%d", 42); |
42 |
%u |
unsigned int | printf("%u", 42); |
42 |
%f |
float / double | printf("%f", 3.14); |
3.140000 |
%.2f |
float (2 decimals) | printf("%.2f", 3.14159); |
3.14 |
%c |
char | printf("%c", 'A'); |
A |
%s |
string (char array) | printf("%s", "Hello"); |
Hello |
%x / %X |
hexadecimal | printf("%x", 255); |
ff / FF |
%o |
octal | printf("%o", 8); |
10 |
%p |
pointer address | printf("%p", &var); |
0x7ffd5... |
%ld |
long int | printf("%ld", 123456789L); |
123456789 |
%lld |
long long int | printf("%lld", 9876543210LL); |
9876543210 |
%e / %E |
scientific notation | printf("%e", 12345.67); |
1.234567e+04 |
Width and Precision
#include <stdio.h>
int main() {
int num = 42;
float price = 9.99;
// Minimum width
printf("[%5d]\n", num); // [ 42] - right-aligned, width 5
printf("[%-5d]\n", num); // [42 ] - left-aligned, width 5
printf("[%05d]\n", num); // [00042] - zero-padded, width 5
// Precision for floats
printf("[%f]\n", price); // [9.990000] - default 6 decimals
printf("[%.2f]\n", price); // [9.99] - 2 decimals
printf("[%8.2f]\n", price); // [ 9.99] - width 8, 2 decimals
// Precision for strings
printf("[%.5s]\n", "Hello World"); // [Hello] - max 5 chars
return 0;
}
Type Casting
What happens when you try to mix different data types? Like adding an integer to a float, or storing a decimal in an integer variable? This is where type casting comes in—it's the process of converting data from one type to another.
9.99 to an int, you get 9—the
decimal part is lost (not rounded, just cut off).
What is Type Casting?
Type casting (or type conversion) is changing a value from one data type to another. C can do this automatically (implicit) or you can force it manually (explicit) using the cast operator.
Implicit: C does it automatically
(smaller to larger type, like int → float). Explicit: You do it manually using
(type) syntax, like (int)3.14 → 3.
Implicit Conversion (Automatic)
C automatically converts smaller types to larger types to prevent data loss:
#include <stdio.h>
int main() {
int num = 10;
float result;
// int automatically converted to float
result = num + 2.5; // 10 becomes 10.0, result = 12.5
printf("Result: %f\n", result); // 12.500000
// char automatically converted to int
char letter = 'A';
int ascii = letter; // ascii = 65
printf("ASCII of %c is %d\n", letter, ascii);
// Type promotion in expressions
int a = 5, b = 2;
float division = a / b; // Integer division: 2.0 (not 2.5!)
printf("5 / 2 = %f\n", division);
return 0;
}
Explicit Conversion (Type Casting)
Use cast operator to force conversion:
#include <stdio.h>
int main() {
int a = 5, b = 2;
float result;
// Without casting: integer division
result = a / b;
printf("Without cast: %f\n", result); // 2.000000
// With casting: floating-point division
result = (float)a / b;
printf("With cast: %f\n", result); // 2.500000
// Converting float to int (truncates decimal)
float price = 99.99;
int rounded = (int)price;
printf("Price: %.2f, Rounded: %d\n", price, rounded); // 99.99, 99
// Character to integer conversion
char digit = '7';
int value = digit - '0'; // Convert char '7' to int 7
printf("Digit: %c, Value: %d\n", digit, value);
return 0;
}
Best Practices
Congratulations on making it this far! 🎉 Before you start writing your own programs, here are some golden rules that will save you hours of debugging and make your code professional from day one.
DO
- Initialize variables when declaring them
- Use meaningful, descriptive variable names
- Use constants for magic numbers
- Always use
&in scanf() for non-arrays - Check return value of scanf() for errors
- Use appropriate data types for your data
DON'T
- Use uninitialized variables
- Use single-letter names (except loop counters)
- Use magic numbers directly in code
- Forget
&in scanf() (undefined behavior) - Mix data types without explicit casting
- Ignore compiler warnings
Complete Example: Student Information
#include <stdio.h>
#define MAX_NAME_LENGTH 50
#define PASSING_GRADE 60
int main() {
// Variable declarations with clear names
char studentName[MAX_NAME_LENGTH];
int studentAge;
float examScore;
char letterGrade;
// Get student information
printf("=== Student Information System ===\n\n");
printf("Enter student name: ");
scanf("%49s", studentName); // Limit input to prevent overflow
printf("Enter age: ");
scanf("%d", &studentAge);
printf("Enter exam score (0-100): ");
scanf("%f", &examScore);
// Determine letter grade
if (examScore >= 90) {
letterGrade = 'A';
} else if (examScore >= 80) {
letterGrade = 'B';
} else if (examScore >= 70) {
letterGrade = 'C';
} else if (examScore >= PASSING_GRADE) {
letterGrade = 'D';
} else {
letterGrade = 'F';
}
// Display results
printf("\n=== Student Report ===\n");
printf("Name: %s\n", studentName);
printf("Age: %d years\n", studentAge);
printf("Score: %.1f%%\n", examScore);
printf("Grade: %c\n", letterGrade);
printf("Status: %s\n", examScore >= PASSING_GRADE ? "PASSED" : "FAILED");
return 0;
}
Key Takeaways
Variables Store Data
Variables are named memory locations. Always declare with a type and initialize before use
Data Types Matter
Choose the right type: int for whole numbers, float/double for decimals, char for characters
Constants are Immutable
Use const or #define for values that should never change in your program
printf() for Output
Use format specifiers (%d, %f, %s, %c) to print different data types correctly
scanf() for Input
Always use & before variable names (except arrays). Match format specifiers to variable types
Type Casting
Convert between types explicitly when needed. Be aware of potential data loss
Knowledge Check
Quick Quiz
Test what you've learned about C programming basics
Comments and Documentation
Comments are notes in your code that the compiler completely ignores. They're for humans— including your future self! Good comments explain why you did something, not just what you did.
What is a Comment?
A comment is text in your source code that is ignored by the compiler. Comments are used to explain code, leave notes, temporarily disable code, or document your program.
Good code is self-documenting (clear variable names, logical structure), but comments add context that code alone can't express.
Single-Line Comments (//)
Use
//for short comments on one line. Everything after//until the end of the line is ignored://) were added in C99. They work in all modern compilers, but very old C89-only compilers won't recognize them.Multi-Line Comments (/* */)
Use
/* */for longer comments that span multiple lines:Documentation Comments
For functions and files, use structured documentation comments. Tools like Doxygen can generate documentation from these:
Comment Best Practices
Good Comments
Bad Comments