Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Welcome to Software Development on Codidact!

Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.

Comments on Detailed explanation of "hello, world" in C?

Parent

Detailed explanation of "hello, world" in C?

+7
−0

I am trying to print "hello, world" on screen in in C using this code:

#include <stdio.h>

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

I typed this down in a text file named main.c and compiled with gcc main.c -O program (or program.exe on Windows) and then ran program - it works and I'm told not to worry about all the details yet.

Still I am looking for a more more in-depth explanation of this code. What does all of this mean, in great detail?


(This is a self-answered Q&A aimed to those who aren't satisfied with the explanation "just accept that this works for now". Accepting this for now would normally be a very sensible approach if you just picked up C or even programming overall, but there are always those who insist on learning all the details still.)

History

1 comment thread

Scope (1 comment)
Post
+7
−0

NOTE: this answer contains a whole lot more information than a beginner reasonably needs to know at this point. It addresses various concepts that one normally encounters further down the road in the learning process.


History
In the 1970s, the book The C Programming Language (B. Kernighan, D. Ritchie) was released and became known as "K&R C" (Kernighan & Ritchie). Dennis Ritchie was the creator of the C language. The first code example from that book looked like this:

#include <stdio.h>

main()
{
  printf("hello, world\n");
}

And since then it has become tradition to start every programming book (for C or any other language) with an example printing the text "hello, world". This historic example above is a bit problematic and not quite up to date, but that's another story.

Functions
Looking at the example from the question instead, main is the name of a function. The { and } mark the beginning and end of that function. Functions are the sections of code in a C program where the actual program execution takes place. The name main is a special function name reserved for the function where the program starts, so it can be regarded as the "mandatory bottom of the program" from where we may call other functions, which in turn may call other functions - but eventually the program execution returns to main. Because of that, it is also the function which can communicate a bit with the OS if desired.

A function may take parameters and it may return a value to the caller. All functions that return something must have (at least) one return statement containing the value to return. For example return 0; returns the integer with value 0 to the caller, since 0 in C code is a so-called integer constant (sometimes also referred to as "integer literal"). All such constants in C have a type, in this case int, which nicely matches the int main return type of the function.

The return statement
As soon as the return statement is executed, the function returns to the caller. Since C executes the source code corresponding to the program from the top to bottom like we read a book, any code we happened to have written below a return statement will not get executed. We can try to modify the example by adding a second printf and note that it will not print anything since it isn't executed:

#include <stdio.h>

int main()
{
  printf("hello, world\n");
  return 0;
  printf("test\n");
}

The value 0 happens to be the value that main should return to the OS after successful program execution. If we return another number, then that number corresponds to some error code. In modern programming it is unlikely that the OS even cares about the return value though, other than displaying it for information. On some consoles you will get this number printed along the form of Program returned: 0 or similar.

Since main is a special function unlike any other, we are actually permitted (as per the C99 standard or later) to entirely omit return 0; from main() and that will have the same meaning as if we had written return 0; explicitly. So in modern/semi-modern C, we can actually safely leave out the return in the specific case of main, but then the program would not be portable to very old C compilers. Try this out:

#include <stdio.h>

int main()
{
  printf("hello, world\n");
}

And that will work just as fine and return 0, unless you are using a very old compiler.

Parameters and the format of main()
The parenthesis in main() corresponds to the parameter list - an optional list of data that the function accepts as input from the caller. Until very recently, an empty parenthesis in a function actually meant "function accepting any parameter", because in the old days of K&R C we could declare function parameters in an alternative way. So main() is actually sloppy style - more correct would have been int main (void) where void means that we take no parameter. In the very recent "C23" version of the language, the old "accept any parameter" style got phased out of the language though, so now int main() and int main(void) are 100% equivalent.

It is important to recognize that the format of the function main() is set by the C standard and the compiler, never by the programmer. The C standard says that for a hosted system (one with an OS), the format must be int main (void) (or in C23, int main() is equivalent). Or in the special case where we wish to pass parameters along to the program when we call it, then the alternative standard form int main(int argc, char *argv[]) is used for that, but I won't go into that one here.

Furthermore, standard C allows compiler-specific forms of main(). For example the standard says that in freestanding systems (embedded), the form of main() is always compiler-specific. In case of hosted systems, compiler-specific forms may exist too. In that case the compiler will document in its manual which alternative form(s) of main() it supports. For example void main (void) is very common. Again, it is the compiler stating which forms that are allowed, never the programmer.

Function declarations versus definitions
Regarding the #include <stdio.h> and printf - the short story is that stdio.h is the library where printf is located and by including it we may use the printf function. The long and detailed story is that the #include makes printf visible to main, by providing a function declaration.

As noted earlier, functions are the part of the program where execution happens. But for a function to call another function, it needs to be made aware of its existence. Normally one makes other functions aware by writing a function declaration, a line of code looking something like this:

int func (char x);

This is a note regarding function usage, for the user of the function and the compiler both, stating this: "Somewhere in the program I have defined a function named func. It returns int and takes a char as parameter. I prefer to call the char parameter x (writing the name of the parameter in a function declaration is actually optional). You may call this function from your program, if you use it like I just showed you." The semicolon at the end signifies that this is a function declaration and that it is now done.

Whereas int main(){ ... } in our example comes with the { and } - a function body with executable code. That is called a function definition - the actual function.

printf, stdio.h and include pre-processing
Now what we like to do from main() is to call a function printf ("print formatted"), which got a function definition somewhere inside a C standard library file that the compiler automatically links to our program when asked for it. We don't actually get to see what the function definition of printf looks like, but for the compiler compiling main() to know about printf and how it is called, we should make a function declaration visible and that will be enough.

The function declaration for printf is located in the header file stdio.h. A header file in C (typically always ending with the extension .h) is a file that contains information of how to use a module or library, but rarely ever any executable code. It may contain constants, types and other things we can use too. stdio.h ("standard input/output") specifically is part of the pre-made standard library that the C standard requires to be present in advance. It is integrated into the C compiler itself.

#include is how we include a header file. The < and > signifies that we want a standard library header, and not a custom one, in which case we would have used " and " instead. Any line that begins with # in C are so-called pre-processing directives, which means that they execute and prepare things for the program before the rest of it is even compiled. What #include does is to grab the header file named stdio.h and between the lines pastes the whole contents of that file into our main source. On a compiler like gcc we can actually look at the file after preprocessing but before compilation, if we compile with the -E option. We will then see many hundred lines of function declarations and the like from stdio.h and then our main() program at the bottom. This state of a .c file after pre-processing, where all the header files it uses are silently "pasted" into it, is formally known as a translation unit, consisting of a single .c file and all the headers it includes.

Once #include <stdio.h> is in place, the compiler can now see the function definition of printf and therfore knows how to call it. As for how the programmer knows how that function works and what it expects, we have to look that up in a book or manual. Basically it is the standard function for formatted output, really a quite complicated function but we don't need to know everything about it just to print some text. The first parameter to printf is the format string where apart from stuff that we print out, like "hello, world", we may also include other commands that printf will parse, leading to special behavior. In this case there is a \n at the end - something beginning with a \ inside a string is known as an escape sequence - simply put a special token or command. \n means "line feed", meaning that after printing "hello, world", there should be a switch to a new line in the output. It is custom to do this so that the next function that wants to print something can assume that printing begins on a new line. Example: had we written "hello\nworld" instead, we would get "hello" and "world" printed on separate lines.

Instead of using printf, we could as well have used a much easier function puts ("put string"). It only knows how to print a string and it always ends the printing with a new line without us asking for it. But it can't do anything else, unlike printf which comes with a lot of various formatting options.

History

2 comment threads

empty parens in function declaration vs definition (3 comments)
What is a "caller"? For example a statement like "A function may take parameters and it may return a ... (2 comments)
What is a "caller"? For example a statement like "A function may take parameters and it may return a ...
Carl‭ wrote 6 months ago

What is a "caller"? For example a statement like "A function may take parameters and it may return a value to the caller." does that mean for a line code like this double a = sqrt(2); is a then the caller?

Lundin‭ wrote 6 months ago

Carl‭ A caller is the function that contains the code calling sqrt. The terms caller and callee are common in programming - I guess I could explain those too in more detail but this answer already got quite long.