FirstHack Learn
Log in Sign up free
Lessons in this course 0/6 All courses C Programming From Zero

First year

Progress0 / 6 lessons
  1. 1. What a program actually is
  2. 2. Variables, types and exact sizes
  3. 3. Input and output with printf and scanf
  4. 4. Control flow and loops
  5. 5. Functions and how the call stack works
  6. 6. Arrays and strings in C

Courses › C Programming From Zero

What a program actually is

From the .c file you type to the machine code your CPU runs, step by step.

9 min read · Lesson 1 of 6 · Free

Your computer cannot read C

This is the first thing to get straight. Your CPU does not understand printf. It does not understand int. It understands numbers — instruction codes, a few bytes each, like "copy this value into that register" and "add these two registers".

C exists for you, not for the machine. It is a language humans can read that sits close enough to the hardware that it can be translated cleanly into those numbers. That translation is called compilation, and the program that does it is the compiler.

So when your lab teacher says "compile the program", they mean: turn my readable text file into a file full of machine instructions the CPU can execute.

The four steps

When you run gcc hello.c -o hello, four separate programs run one after another. Most students think it is one step. It is not, and knowing the four saves you hours when an error appears.

  1. Preprocessor — handles every line starting with #. #include <stdio.h> is literally replaced by the entire text of the file stdio.h. #define PI 3.14 makes the preprocessor find every PI and swap in 3.14. No compiling happens here. It is text substitution.
  2. Compiler — takes that expanded text and produces assembly, then object code. This is where syntax errors come from. A missing semicolon dies here.
  3. Assembler — turns assembly into an object file, hello.o. Real machine bytes now, but not runnable yet.
  4. Linker — joins your object file with the C standard library, so that the printf you called actually points at real code. "undefined reference to printf" is a linker error, not a compiler error.
ℹ️

You can see the stages yourself. gcc -E hello.c stops after the preprocessor and prints the expanded file. Try it once. A 5-line hello world becomes over 700 lines. That is stdio.h being pasted in.

The smallest real program

C
#include <stdio.h>

int main(void)
{
    printf("Hello, world\n");
    return 0;
}

Read it line by line, because every word is doing a job.

#include <stdio.h> brings in the declaration of printf. Without it the compiler does not know what printf is or what arguments it takes.

int main(void) is where execution starts. Not the top of the file — the top of main. The operating system calls main for you. int means main hands a number back to the OS when it finishes. void means main takes no arguments.

printf("Hello, world\n") calls a function from the standard library. \n is one character, not two: it is a newline. Leave it out and your output sticks to the next command in the terminal.

return 0; tells the OS "I finished successfully". Any non-zero value means an error. This is not decoration. Shell scripts and automated test systems read that number.

Compiling and running it

C
/* Save as hello.c, then in the terminal:
 *
 *   gcc hello.c -o hello
 *   ./hello
 *
 * Output:  Hello, world
 */
#include <stdio.h>

int main(void)
{
    printf("2 + 2 = %d\n", 2 + 2);
    return 0;
}

-o hello names the output file. Leave it out and gcc produces a file called a.out. That is why half the class has a mystery a.out sitting in their folder.

⚠️

void main() is wrong, even though it compiles on Turbo C and your seniors' notes use it. The C standard says main returns int. Write int main(void). In a viva, "why int and not void" is a very common question, and the answer is: so the program can report success or failure to the operating system.

Errors are not failure

A compiler error means the compiler could not understand you. It always prints a line number. Start at the first error, not the last — one missing brace can produce forty errors below it, and fixing the first often clears all of them.

Turn on warnings from day one:

C
/* Compile with:  gcc -Wall -Wextra hello.c -o hello  */
#include <stdio.h>

int main(void)
{
    int x = 5;
    printf("x is %d\n", x);
    return 0;
}

-Wall -Wextra makes gcc tell you about code that is legal but almost certainly a mistake. Students who use these flags spend far less time debugging.

What to do now

Type the hello world by hand. Do not copy-paste. Compile it. Break it on purpose: delete the semicolon, delete the #include, change int main to int mian. Read each error message. You are learning to read the compiler, and you will read it every day for the rest of your degree.