Structure of a C program
I am Jyotiprakash, a deeply driven computer systems engineer, software developer, teacher, and philosopher. With a decade of professional experience, I have contributed to various cutting-edge software products in network security, mobile apps, and healthcare software at renowned companies like Oracle, Yahoo, and Epic. My academic journey has taken me to prestigious institutions such as the University of Wisconsin-Madison and BITS Pilani in India, where I consistently ranked among the top of my class.
At my core, I am a computer enthusiast with a profound interest in understanding the intricacies of computer programming. My skills are not limited to application programming in Java; I have also delved deeply into computer hardware, learning about various architectures, low-level assembly programming, Linux kernel implementation, and writing device drivers. The contributions of Linus Torvalds, Ken Thompson, and Dennis Ritchie—who revolutionized the computer industry—inspire me. I believe that real contributions to computer science are made by mastering all levels of abstraction and understanding systems inside out.
In addition to my professional pursuits, I am passionate about teaching and sharing knowledge. I have spent two years as a teaching assistant at UW Madison, where I taught complex concepts in operating systems, computer graphics, and data structures to both graduate and undergraduate students. Currently, I am an assistant professor at KIIT, Bhubaneswar, where I continue to teach computer science to undergraduate and graduate students. I am also working on writing a few free books on systems programming, as I believe in freely sharing knowledge to empower others.
Welcome to one of the most fundamental concepts in C programming! Before you start writing complex programs, it's essential to understand how a C program is organized. Think of the structure of a C program like the blueprint of a house — every part has a specific purpose and place.
C, created by Dennis Ritchie at Bell Labs in the early 1970s, has a clean and logical structure that has influenced countless programming languages. Once you understand this structure, writing C programs becomes much more intuitive.
A Simple C Program
Let's start with the classic "Hello, World!" program and understand each part:
#include <stdio.h>
int main() {
printf("Hello, World!\n");
return 0;
}
Even this simple program contains all the essential structural elements. Let's explore each one in detail.
The Six Main Components of a C Program
A complete C program can have up to six major sections. Not all sections are required in every program, but understanding each one is crucial.
1. Documentation Section (Comments)
The documentation section contains comments that describe the program. Comments are ignored by the compiler but are invaluable for humans reading your code.
/*
* Program Name: Temperature Converter
* Author: Your Name
* Date: December 2024
* Description: This program converts temperature from
* Celsius to Fahrenheit and vice versa.
*/
Why is this important?
Helps others (and your future self) understand what the program does
Documents the author, date, and version information
Explains complex logic or algorithms
Two types of comments in C:
| Type | Syntax | Use Case |
| Single-line | // comment | Brief explanations |
| Multi-line | /* comment */ | Longer descriptions, headers |
// This is a single-line comment
/* This is a
multi-line comment
spanning several lines */
2. Preprocessor Directives (Link Section)
Preprocessor directives are instructions to the C preprocessor, which processes your code before compilation. They always begin with a # symbol.
#include <stdio.h> // Standard Input/Output functions
#include <stdlib.h> // Standard Library functions
#include <string.h> // String handling functions
#include <math.h> // Mathematical functions
#define PI 3.14159 // Constant definition
#define MAX_SIZE 100 // Maximum array size
Understanding #include:
The #include directive tells the compiler to include the contents of another file. Think of it as copying and pasting the contents of that file into your program.
<filename>— Searches in standard system directories (for standard library headers)"filename"— Searches in the current directory first, then system directories (for your own header files)
#include <stdio.h> // System header file
#include "myheader.h" // Your custom header file
Understanding #define:
The #define directive creates symbolic constants or macros. The preprocessor replaces every occurrence of the identifier with its defined value.
#define GRAVITY 9.8
#define SQUARE(x) ((x) * (x))
// Usage:
float force = mass * GRAVITY; // GRAVITY becomes 9.8
int result = SQUARE(5); // Becomes ((5) * (5)) = 25
Common Header Files You Should Know:
| Header File | Purpose | Common Functions |
stdio.h | Input/Output operations | printf(), scanf(), fopen() |
stdlib.h | General utilities | malloc(), free(), exit() |
string.h | String manipulation | strlen(), strcpy(), strcmp() |
math.h | Mathematical functions | sqrt(), pow(), sin() |
ctype.h | Character handling | isalpha(), toupper() |
time.h | Date and time | time(), clock() |
3. Global Declaration Section
This section is used to declare global variables and function prototypes that can be accessed from anywhere in the program.
#include <stdio.h>
// Global variables
int globalCounter = 0;
float taxRate = 0.18;
char programName[] = "My Application";
// Function prototypes (declarations)
void displayMenu();
int calculateSum(int a, int b);
float calculateArea(float radius);
int main() {
// main function code
return 0;
}
Global Variables:
Declared outside all functions
Accessible from any function in the program
Exist for the entire duration of the program
Should be used sparingly (prefer local variables when possible)
Function Prototypes:
A function prototype tells the compiler about a function's name, return type, and parameters before the actual function definition appears. This is also called a function declaration.
// Function prototype (declaration)
int add(int x, int y);
int main() {
int result = add(5, 3); // Compiler knows about add() from prototype
printf("Sum: %d\n", result);
return 0;
}
// Function definition (comes after main)
int add(int x, int y) {
return x + y;
}
Why use function prototypes?
Allows you to call functions before defining them
Helps the compiler catch errors (wrong number or type of arguments)
Makes your code more organized (main function can appear first)
4. The main() Function
The main() function is the heart of every C program. It's where program execution begins and ends.
int main() {
// Your code goes here
return 0;
}
Anatomy of main():
| Component | Meaning |
int | Return type (main returns an integer to the operating system) |
main | Function name (must be exactly this) |
() | Parameter list (can be empty or contain command-line arguments) |
{ } | Function body (contains all executable statements) |
return 0; | Returns 0 to indicate successful execution |
Two valid forms of main():
// Form 1: No command-line arguments
int main() {
return 0;
}
// Form 2: With command-line arguments
int main(int argc, char *argv[]) {
// argc = argument count
// argv = argument vector (array of strings)
return 0;
}
Understanding the return value:
return 0;— Program executed successfullyreturn 1;(or any non-zero) — Program encountered an error
The operating system uses this return value. For example, in shell scripting, you can check if a program succeeded or failed.
5. User-Defined Functions
Beyond main(), you can create your own functions to organize code into reusable, logical blocks.
#include <stdio.h>
// Function to calculate the area of a rectangle
float calculateRectangleArea(float length, float width) {
float area = length * width;
return area;
}
// Function to display a greeting
void greetUser(char name[]) {
printf("Hello, %s! Welcome to the program.\n", name);
}
// Function to check if a number is even
int isEven(int number) {
if (number % 2 == 0) {
return 1; // True
} else {
return 0; // False
}
}
int main() {
greetUser("Student");
float area = calculateRectangleArea(5.0, 3.0);
printf("Rectangle area: %.2f\n", area);
if (isEven(10)) {
printf("10 is even\n");
}
return 0;
}
Parts of a function:
return_type function_name(parameter_list) {
// Local variable declarations
// Executable statements
return value; // If return_type is not void
}
Common return types:
int— Returns an integerfloat— Returns a floating-point numberdouble— Returns a double-precision floating-point numberchar— Returns a single charactervoid— Returns nothing
6. Local Declarations and Statements
Within any function (including main()), you have local declarations and executable statements.
int main() {
// Local variable declarations
int age;
float salary;
char grade;
int numbers[5];
// Executable statements
age = 20;
salary = 50000.50;
grade = 'A';
printf("Age: %d\n", age);
printf("Salary: %.2f\n", salary);
printf("Grade: %c\n", grade);
return 0;
}
Important rules:
In older C standards (C89/C90), all variable declarations must appear at the beginning of a block, before any executable statements
In modern C (C99 and later), you can declare variables anywhere in the block
Local variables only exist within the function or block where they're declared
Complete Program Example
Let's put everything together in a complete, well-structured program:
/*
* Program: Simple Calculator
* Author: Jyotiprakash
* Date: December 2024
* Description: A basic calculator that performs
* addition, subtraction, multiplication, and division.
*/
// Preprocessor Directives
#include <stdio.h>
#include <stdlib.h>
#define PROGRAM_VERSION "1.0"
// Global Declarations
const char* programName = "Simple Calculator";
// Function Prototypes
void displayWelcome();
void displayMenu();
float add(float a, float b);
float subtract(float a, float b);
float multiply(float a, float b);
float divide(float a, float b);
// Main Function
int main() {
// Local declarations
int choice;
float num1, num2, result;
// Display welcome message
displayWelcome();
// Main program loop
while (1) {
displayMenu();
printf("Enter your choice (1-5): ");
scanf("%d", &choice);
if (choice == 5) {
printf("Thank you for using %s!\n", programName);
break;
}
if (choice < 1 || choice > 5) {
printf("Invalid choice. Please try again.\n\n");
continue;
}
printf("Enter first number: ");
scanf("%f", &num1);
printf("Enter second number: ");
scanf("%f", &num2);
switch (choice) {
case 1:
result = add(num1, num2);
printf("Result: %.2f + %.2f = %.2f\n\n", num1, num2, result);
break;
case 2:
result = subtract(num1, num2);
printf("Result: %.2f - %.2f = %.2f\n\n", num1, num2, result);
break;
case 3:
result = multiply(num1, num2);
printf("Result: %.2f × %.2f = %.2f\n\n", num1, num2, result);
break;
case 4:
if (num2 == 0) {
printf("Error: Division by zero is not allowed!\n\n");
} else {
result = divide(num1, num2);
printf("Result: %.2f ÷ %.2f = %.2f\n\n", num1, num2, result);
}
break;
}
}
return 0;
}
// User-Defined Functions
void displayWelcome() {
printf("================================\n");
printf(" %s v%s\n", programName, PROGRAM_VERSION);
printf("================================\n\n");
}
void displayMenu() {
printf("--- Menu ---\n");
printf("1. Addition\n");
printf("2. Subtraction\n");
printf("3. Multiplication\n");
printf("4. Division\n");
printf("5. Exit\n");
}
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 a / b;
}
Structure at a Glance
┌─────────────────────────────────────────┐
│ 1. DOCUMENTATION SECTION │
│ (Comments describing the program) │
├─────────────────────────────────────────┤
│ 2. PREPROCESSOR DIRECTIVES │
│ (#include, #define) │
├─────────────────────────────────────────┤
│ 3. GLOBAL DECLARATIONS │
│ (Global variables, prototypes) │
├─────────────────────────────────────────┤
│ 4. main() FUNCTION │
│ ┌─────────────────────────────┐ │
│ │ Local declarations │ │
│ │ Executable statements │ │
│ │ return 0; │ │
│ └─────────────────────────────┘ │
├─────────────────────────────────────────┤
│ 5. USER-DEFINED FUNCTIONS │
│ (Your custom functions) │
└─────────────────────────────────────────┘
Key Points
Every C program must have a
main()function — This is where execution begins.Preprocessor directives come first —
#includeand#defineare processed before compilation.Comments are your friends — Document your code generously. Your future self will thank you.
Function prototypes enable flexibility — Declare functions before
main(), define them after.Local vs. Global scope matters — Prefer local variables; use global sparingly.
Consistent structure improves readability — Follow a standard organization for all your programs.
The semicolon is mandatory — Every statement in C ends with a semicolon (except preprocessor directives and function definitions).
Practice Exercise
Try writing a program that follows the complete structure we discussed. Here's a challenge:
Create a program that:
Has proper documentation comments
Includes necessary header files
Defines a constant for PI using
#defineDeclares function prototypes
Contains a
main()function that calculates the area and circumference of a circleUses separate functions for
calculateArea()andcalculateCircumference()