Introduction to C: Hello, World

First I'd like to show you one of the simplest possible C programs. It's the classic many have learned first: Hello, World.

#include <stdio.h>

int main(int argc, char* argv[])
    printf("Hello, world!\n");
    return 0;

I'll explain what it does line-by-line.

Video Walkthrough
Source Code

Source code for this lesson is available on GitHub.

Importing from another file

The first line, #include <stdio.h>, allows the use of the standard input/output library in our program.

The #include statement allows another file to be included in your program. In C, header files generally end in .h and specify functions for a corresponding .c file (or set of .c files).

Notice that the #include statement was used with angle brackets, otherwise known as < (less than) and > (greater than) characters. This generally instructs the C compiler's pre-processor to look for stdio.h on the system's include path. You can also use double-quotes, such as #include "stdio.h", but conventionally this format is used for header files you define yourself. By using angle brackets, the system headers may be preferred over header files present in your own project. However, this behavior can vary on a per-project and per-compiler basis.

The stdio.h header file includes function definitions for input/output (I/O) function calls that the standard library supports, thus defining them in our program later potential use. (In another lesson, we'll create our own header file.)

Defining a function for use as the entry-point

Writing int main(int argc, char* argv[]) { ... } defines a function called main. In C, if you name your function main(), it will be used as the entry point. The curly braces indicate the start of a scope. In C, you can only access variables declared in the current scope, or an outer scope.

The C language is parsed based on tokens. The C compiler doesn't consider spaces, tabs, or newlines to be significant. So if for some reason you wanted to put all the code on a single line, you could do that. There are even contests to see who can come up with the most unreadable C code. Generally, when programming in C, you should write your code in a consistent style.

Calling another function

The printf(...); line will call a function (defined because of the #include <stdio.h> line above and pass in the text "Hello, world!\n". The \n within the string is a newline character. (Unlike the print functions in some languages, C does not automatically add a newline for you.)

In C, statements must be terminated by a semi-colon (;). Typically, these are placed at the end of each line, but in some cases you may see them in the middle.

Returning from a function

The return 0; line will cause the main function to terminate, and pass a value of 0 to its caller. In this case, the caller is the executable loader, which will use the returned value as the exit code of the program. Generally, you want the exit code to be zero if the program succeeded, and non-zero if the program fails. Some programs will return a different value to indicate what type of error occurred.

Notice that there are no ( and ) (parentheses) characters when using return. That is because return is not a function; it is a keyword. In C, keywords are considered reserved words and cannot otherwise be used in your program. For example, you cannot name a function "return()".

The value passed to the return keywords must match the return type specified by the function definition. When we defined the main() function, we wrote intmain(...) to specify that the return type is an integer. In C, an int is a built-in data type that refers to a whole number that can be negative or positive. Basic integer types in C are signed unless you specifically use the unsigned keyword.

Compiling and Running

To run a program written in C, it must first be compiled into an executable. To do this, you can use the cc program, which generally invokes the C compiler on any UNIX-like system.

$ cc -o main main.c
$ ./main
Hello, world!

If cc is not found, you will first need to install it. For example, on an Ubuntu system, you would run sudo apt-get install build-essential. (On a Windows PC, you can get Ubuntu from the Microsoft store, and then run that.) On a Mac, you can install Xcode from the app store, then run it and accept the license agreement.

Compiler Options

Usually, cc is run with additional options. More options will be covered in future lessons, but for now, here are some additional options you should be aware of:

  • -Wall: Causes warnings to be printed while compiling your code, when the compiler encounters code that could be incorrect. This option won't catch every problem with your code, but is useful to ensure that your code is generally correct and standards-compliant.
  • -Werror: Causes the compiler to treat all warnings as errors. This will abort the compiler, rather than allowing code that compiles with warnings to be included in your software (at your own peril).
  • -std=<standard>: Specifies which version of the C standard to use when compiling your code. For this project, we'll use -std=c11, which will use the 2011 version of the C standard. c99 and c90 are other common versions of the C standard that may be used.
  • -g: Includes debugging information in the executable file. Including this option increases the size of our program, but can help when diagnosing crashes, or running our program in a debugger, such as gdb.

To find out what other options cc supports, you can type man cc to review the manual. These options are not standardized, and may vary depending on the compiler you are using. Many compilers are based on gcc, which commonly supports these options (and many more).

Since we'll want to use these options every time we compile, in the next lesson we'll write a Makefile that will take care of building our program, so we don't have to run the compiler manually every time.


By now, you've learned how to compile and run the most basic C program. In the next lesson, I'll show how to create a simple Makefile to make compiling your code easier.