Showing posts with label hello world. Show all posts
Showing posts with label hello world. Show all posts

Wednesday, May 12, 2010

My Hello World

As I have mentioned in my previous post, I have not liked the way most C or C++ books begin. They start with a program that prints hello world and attempts to create enough enthusiasm among the readers to lure them to continue reading the fat book. This approach puts undue stress on experiencing the output without really speaking anything about computers or the C/C++ programming language. Moreover, the first program that the beginners write is so difficult and tricky that few will understand its true genius even after completing the entire book.

If I teach C, I want to start off differently. I want to include the least number of constructs in the first program. My first program will be an infinite while loop. It will look like this.

void main()
{
    while(1);
}

Now that is a beauty. I would tell that all C/C++ programs had one (and only one) main function. The main is the entry point into the program. The CPU will start executing the program from this point. The first word of the program represents what kind of output this program will produce. It is known as a return value. “void” means nothing. So we are declaring that this program will not produce any output. Some implementations of the C language may require that the main function produce some output. For such implementations we would replace the “void” with “int” (for integer value) and add one more statement just after the while(1); - return 0;

The round brackets after main have a special purpose. We will talk about those later. There are curly brackets after this. They define the scope. Think of a closed box with its name stamped on its cover and the kind of value (integer / void) that comes out of it, stamped before the name. Then, the name will be “main” the kind of value is the int or void written before main. The periphery of the box then, are the curly brackets.

Whatever is inside the curly brackets will be executed by the CPU, one statement at a time. In the simplistic demo program, we have a single statement that says while(1); The word while is different from the word main. "while” is a keyword. There are only a few number of keywords in C/C++ and they have a specific meaning. The “while” keyword is a looping construct. It asks the CPU to execute whatever comes after “while” for as many times as required until the condition inside the () becomes false. Of course, it may never become false at all in which case the CPU will keep executing the instructions ad infinitum.

True and False are tricky in conditional checks in C. Anything that evaluates to 0 is considered false and all non-zero values are considered true. Hence, the condition inside the round bracket will always evaluate to true (since it is non-zero) and the loop will continue forever. But there is nothing inside the loop. The loop boundary could have been defined by the same scope defining {} as for “main”. Instead, in their place, we have a semicolon (;). Hence no statements are to be executed inside the loop. All the CPU does is keep checking the condition, over and over again. Really, the computer is a dumb box.

Your first program does not produce any output. It causes the computer to hang! The condition inside the while loop () can be a more complex one. It could be a comparison such as 5>2, which would always evaluate to true or another such as 1!=1, which stands for one not equal to one which always evaluate to false. The C language supports many operators and we will explain then as and when we use them.

Friday, January 15, 2010

Why I dislike the C Hello World program

The computer is a machine that takes input, processes it and produces some output. This is a great definition in its own, but not without flaws. Many have argued that there might be some programs which do not take input from the user and still produce an output. One such example is the common Hello World program that one will encounter in all major programming language books. All that such a program does is print the words “Hello World” on the screen. This is how a C Hello World program looks like.
#include < stdio.h >
int main()
{
printf("Hello World\n");
return 0;
}

Look at this monster. It is a very complicated program to understand, unlike what a Hello World must be. Worse still, many students face this monster on the very first day of their programming lessons. It took me many years to completely comprehend what is happening in that program and then started hating this program. Let us start from the very beginning.

A program written in the C or C++ language goes through a series of operations when we compile it. At the end of the compilation process, an exe file is created which contains machine level code that can be executed by the underlying microprocessor. To print “Hello World” on the screen, we need to convert this program in to the machine readable format. The microprocessor then must understand that the characters have to be rendered into the frame buffer of the screen to appear on the physical screen.

Even before the compiler can convert this program into a machine readable format, something else needs to be done. The #include is a preprocessor directive. A small program called the preprocessor acts on all the commands starting with a hash (#). The #include command asks the preprocessor to copy the contents of another file into the text of this file. The included file in turn may include more files within itself. A fully expanded version of the C program is much larger than the 6 line program here. The standard IO header file (stdio.h) contains information about how to display characters on the output device and how to take input from the user.
Then comes the magic function main. The main function is always required in any C or C++ program. It is defined as the entry point of a program, but is it really so? If we do not specify the main function, the Visual C++ linker will give the following error: LINK : fatal error LNK1561: entry point must be defined

Therefore, main must be defined. But that does not mean that it is the entry point, or the very first thing that is executed in a program. Look at this second program.


#include < stdio.h >
#include < conio.h >
int func1();

int a = func1();
int b=func1()+100;

void main()
{
printf("a=%d, b=%d\n", a, b);
getch();
}

int func1()
{
printf("Entered func1()\n");
main();
return 10;
}


The main is not the first function to be executed. In fact, another function is executed because its return value is to be applied to a global variable. All global variables are evaluated before the entry point function is called. What this essentially means is that one may write an entire program without ever going inside the main function. Just create a global function and a global variable that takes the return value of this global function and write the entire program inside this global function. After all the processing is done, just call exit() before returning. In such a program, the main function will exist only to please the linker. It will never be called!

Having creased the foreheads of many teachers with the difficulty of explaining this simple program, let us move to the printf function. What does this function do? It prints the characters inside the quotes on screen. But as a side effect, it also returns the number of characters printed. Most real programs never use the return value from printf, but most interview questions do. What is even more intriguing about the printf function is that it is able to take any number of parameters. How do we write such a function? The printf function uses something called as the variable arguments facility present in the C construct. While declaring a function, you may say that there might be any number of parameters to a function. In the definition of the function, one would act on all these parameters. Within the quotes, one may specify certain special character sequences to indicate that a value from some variable will be plugged into at this place. Typical usage is:
printf(“a=%d, b=%d”, a, b);

The number of % sequences inside the quotes specifies the number of variables that will follow. One may specify more or less variables, and depending on the compiler, the additional variables may be ignored and the lesser variable values may be displayed as garbage. The way such a function is defined is by using ellipses (…) inside the function definition.

int printf(char *_Format, ...);

It was not before my final year of engineering, when we wrote a logging function for our project, that I first wrote a function using the ellipses. At that time, just giving … on Google Search yielded a blank page with no results and nothing written below the Google search bar. It has changed since then.

By introducing the printf function on the very first day of programming, we actually introduce a monster whose true value is never appreciated by most students.
Now let us look at the final statement. We are returning a zero. This is in line with the main function having promised that it will return an int in its definition. But who are we retuning to? This brings us to the discussion of how a program is run. After an executable of some kind has been created, a program known as the loader is kicked in. The program is run by the Unix shell or by a DOS terminal; the program will return control to the respective parent. The return value will be accessible before executing any other program.

Still, this Hello World program is most commonly taught as the first program to students. Most people think that it is as simple as it gets. Students are only satisfied if they see some output on the screen. I shall not argue, but I do expect the teachers to one day go back to the hello world program and appreciate the real complexities of these simple 6 lines of C code.
I hope my explanation proves helpful to someone.