The classic “Hello world” C program from a different perspective

Tobias Aguiar
5 min readDec 16, 2022

--

Observe the following lines :

#include <stdio.h>

int main(int argc, char** argv) {

printf("Hello World!");

return 0;
}
Photo by Zach Graves on Unsplash

Yes, it is only a basic C programming where we show a “Hello world” message through the standard output.

At first sight you may look and tell me, there is nothing to discuss about with these few lines of code.

Maybe you’re right, maybe not. So let’s mix some programming with other interesting topics and let’s take a closer look at this piece of Software!

Include? Including what?

Let’s start with

#include <stdio.h>

files that use other files

If you’re familiar with programming you know that <something>.h is called header file. Put in simple world, the header file is a file which contains specififc declarations (such as macro definitions) and function prototypes that will be used and shared among different source files (<something>.c in this case).

The word stdio stands for standard input/output. With these two information together, we can conclude : the <stdio.h> header file is a standard C file which contains functions prototypes and others specifics declaration that are responsable for handling input/output stream.

You can’t get away from it

That’s why, in every basic simple C program, you need to include at least this file, otherwise you won’t be able to manipulate your code. A software program is a system where you give it an input, and it produces an output as a response, as every system in the world. If you can’t manipulate input/output properly, you can’t really use the program.

So this file makes your life easier and gives ready functions that handles the input/output stream in a complex low-level way, where your job is just call this functions. Wonderful, isn’t it?

What is main?

That begins the interesting part.

int main(int argc, char** argv) {

//we get to printf later

return 0; // we also get to this later
}

Let’s refresh what happens :

. You write the main function (it can even take arguments, interesting, right?).

.You compile and execute the output generated

In neither of these steps you call the main function. How is it called? But first, what is the main() function?

Your computer is dumb

That’s why we need a main function. Because your computer does not know where is your code! And that’s when the main function comes in : it works as the entry point of your execution program, it will let the Operating System know where your program begins, and then it will execute it!

Calling a function that is not really called?

Yes it is called, but you just don’t see it, as well as a lot of another buch of things you don’t see before your program starts running, because it’s hidden in the compilation process which produces your executable.

I won’t dwell on the details because I want to keep the article the simplest I can.

How does it know the arguments?

Because this is a built-in function, so it comes already with predefined arguments. The most used ones are :

  • Argc : the number of arguments your program will take.
  • Argv : A character string representing each one of your arguments.

Printing a message? Where? How?

Let’s go to the printf part!

It is only a one-word function call, but have you ever wondered what is behind the hood in this function?

Did you know that the implementation of this function takes a few thousand lines? In a few words, it does the following routine :

  • take an address in memory of a buffer (or a character string).
  • write its content in the standard output of your program (for those who might not know what I’m talking about, the screen where your execute your program – it can vary from OS to OS).

But wait, if you’re going to access the memory, you’re trying to get information from the hardware! I’m sorry but you can’t do that from your program, because you are in a different space from the hardware resources. Let me explain.

User space vs kernel space

user space vs kernel space, you can find the picture here

When you’re in a program and, for some reason, you need to access resources from the hardware, your OS changes what we called the privilege mode.

The lower the layer it is going through, the more priviliged it is. It is responsible of being the interface between your program which needs a hardware resources and the hardware itself.

So the OS accesses these resources through a mechanism called system call. We can talk more about this topic in another article.

Returning a value? Why? And for who?

As well as you give your OS an entry point to properly execute your program, you also need to give it an exit point so it will know your program has finished.

You can rerturn different values, but in generall you return zero when you program was executed successfully without errors, and ir return a positive value otherwise.

Conclusion

As you could see, a few lines of code can turn into some dense and complex discussions that sometimes we don’t notice. If I wanted, I could make a 7000+ word article giving more details about the topics I mention.

This is a topic that I find really interesting, although very complex : low-level code development.

Sometimes it’s hard to read such articles even for me, but it’s those difficulties that makes us grow in knowledge, right?

Hope you find these lecture somehow useful. Happy reading/coding!

--

--

Tobias Aguiar

Software developer | Trying to make complex concepts look easy | Want help or discuss about embedded software development? Email me! tobi.aguiar01@gmail.com