Chapter 3: The C Language Basics
This chapter introduces the essential syntax of C: what makes up a program, how functions are defined and called, how to use comments and names, how input and output work, and how expressions form the flow of computation. From here onward, you will start writing code that actually does things.
The structure of a C program
A C program is a set of declarations and function definitions, with one function named main acting as the entry point. Before functions, you may include headers and declare global variables. The general form looks like this:
#include <stdio.h>
int main(void)
{
printf("Program skeleton\n");
return 0;
}
Programs are usually composed of several translation units (.c files) compiled separately and linked together. Each file can include one or more header files (.h) that declare shared interfaces.
Typical source layout
Here's how you might typically layout C source code:
| File | Purpose |
main.c | Contains main() and program logic |
util.c | Contains helper functions |
util.h | Declares helper function prototypes |
Makefile | Describes how to build the program |
Functions and the main() entry point
Functions are the building blocks of a C program. Each function has a return type, a name, and (optionally) parameters. The function main() is special because execution begins there. It can take zero or two arguments and must return an int value.
Defining and calling functions
Functions are defined and called like this:
#include <stdio.h>
int add(int a, int b)
{
return a + b;
}
int main(void)
{
int sum = add(3, 4);
printf("Sum is %d\n", sum);
return 0;
}
The function add() receives two integers, computes a result, and returns it. main() then prints the result using printf(). Every function definition must specify a return type. If there is no meaningful value to return, use void.
Return codes and conventions
By convention, returning 0 from main() indicates success. Any nonzero value signals an error. This pattern lets shell scripts and other programs test whether your program ran successfully.
return statement, the result is undefined. Always return explicitly.
Comments, identifiers, and keywords
Comments document your code for readers (including future you). Identifiers name variables, functions, and other symbols. Keywords are reserved by the language and cannot be used as identifiers.
Comment styles
You have a choice of commenting styles:
/* This is a block comment
that can span multiple lines */
int main(void)
{
// This is a single-line comment
printf("Comments ignored by compiler\n");
return 0;
}
Use comments sparingly but clearly. They should explain *why* code exists, not restate what it does.
Valid identifiers
An identifier can contain letters, digits, and underscores, but it must not start with a digit. Identifiers are case-sensitive. Examples: count, file_index, MAX_SIZE.
Common keywords
Here are some of the more common C keywords:
| Category | Examples |
| Types | int, char, float, double, void |
| Control | if, else, for, while, switch, break, continue |
| Storage | static, extern, register, auto, const, volatile |
| Other | return, sizeof, typedef, struct, enum, union |
integer instead of int) to reduce confusion and improve readability.
Basic I/O and formatted output
C’s standard input and output library, <stdio.h>, provides printf() for writing text and scanf() for reading it. Both use format strings containing placeholders that match variable types.
Printing values
This is how you print values to the screen:
#include <stdio.h>
int main(void)
{
int age = 30;
double pi = 3.14159;
printf("Age: %d\n", age);
printf("Pi: %.2f\n", pi);
return 0;
}
Each % marker is replaced by the corresponding argument. The \n creates a newline. Format specifiers control how values are shown: %d for integers, %f for floating-point numbers, %s for strings, and so on.
Reading input
You can read input like this:
#include <stdio.h>
int main(void)
{
int number;
printf("Enter a number: ");
scanf("%d", &number);
printf("You entered %d\n", number);
return 0;
}
scanf() requires the address of the variable (hence the & operator). If the format and input do not match, undefined results may occur, so validate carefully.
scanf() can be unsafe if not used cautiously. For robust programs, prefer line-based input (fgets() and sscanf()) when processing strings.
Common format specifiers
Here are some of the more common format specifiers:
| Specifier | Meaning |
%d | int |
%ld | long |
%f | float or double (depending on context) |
%.2f | floating-point with 2 decimal places |
%s | null-terminated string |
%c | single character |
printf() output when printing to a terminal; many systems buffer text until a newline is written.
Statements, expressions, and blocks
Statements are the executable steps of a program. Expressions compute values. A block (a group of statements in braces) counts as a single compound statement. Understanding this hierarchy is essential to writing readable and structured C code.
Simple and compound statements
Examples of simple and compound statements:
int x = 10; // simple statement
x = x + 5; // expression statement
if (x > 12)
{
printf("x is greater than 12\n"); // part of a compound block
}
Braces define a block scope. Variables declared inside a block are visible only within it. Indentation and consistent style make nested structures easier to follow.
Expressions and side effects
An expression has a value. An expression statement uses that value or triggers a side effect. For example, x++ increments x as a side effect. Control statements such as if or while depend on expressions that evaluate to true (nonzero) or false (zero).
if (x = 5)), it’s easy to introduce logic bugs. Use parentheses and clear comparisons (==) to avoid mistakes.
Program flow at a glance
Each statement executes in sequence unless control flow alters it. You’ll explore conditionals and loops in the next chapter, but the foundation (expressions forming statements within blocks) is already in place here.