Tuesday, February 22, 2011

A return to C programming: Hello world example

I took up C programming at Camp Aguinaldo in the mid 80's and got a certificate for it. but I never earned a centavo for my C programming skills in my later work since the oppurtunity to program was non-existent, instead I opted to enrol in an MS Applied Math, Major in Computer Science after work.

C may be considered a higher level assembly language as the power constructs in assembly are also available in C; concepts such as pointers, unrestricted gotos, and the like. In fact a C compiler worth its salt should be able to generate assembly output!

For the hello world example in C, we try to write in an undiciplined manner and see if we can get away it. As usual we write a function to do the actual writing of a message "hello world!" to be closer in spirit to the previous Javascript example. Save the following to a file "hello.c" without the quotes.

void showMessage(char *str)
{
   puts(str);
}

main()
{
    showMessage("Hello World");
}


Every C program has a main function. The difference between a function and procedure is that the former exlicitly returns a value while a procedure does not and should be declared of type void. Now lets try to run the hello.c code in the console: type

gcc -Wall hello.c

Notice the -Wall flag to output any warnings encountered in processing the source file.
Here is the output from my Ubuntu 10.04 terminal (console):


gcc -Wall hello.c
hello.c: In function ‘showMessage’:
hello.c:4: warning: implicit declaration of function ‘puts’
hello.c: At top level:
hello.c:8: warning: return type defaults to ‘int’
hello.c: In function ‘main’:
hello.c:10: warning: control reaches end of non-void function
toto@toto-laptop:~/Blogs/my-other-life-as-programmer/C$


In good C programs, all functions must be declared and return types should be explicit. Here the compiler complains that puts was implicitly declared and that the main function did not return any value! and yet in spite of these warnings, you will find that the gcc outputte an executible file hello. To run this ececutible, issue ./hello. The program outputs


toto@toto-laptop:~/Blogs/my-other-life-as-programmer/C$ ./a.out
Hello World
toto@toto-laptop:~/Blogs/my-other-life-as-programmer/C$


Now a good C programmer tries to remove all warnings. So lets do some modifications to be in good terms with the gcc compiler.


#include 

void showMessage(char *str)
{
   puts(str);
}

int main() # explicit declaration.
{
    showMessage("Hello World");
    return 0;
}


We have included the standard header "stdio.h", gcc knows where to find it (in "/usr/include") and this erases the warning on puts. We also explicitly declare the main function as type int and specifically return a zero (the usual value for successful execution.) The compilation is now successful without any complaints from the compiler.


toto@toto-laptop:~/Blogs/my-other-life-as-programmer/C$ gcc -Wall hello.c
toto@toto-laptop:~/Blogs/my-other-life-as-programmer/C$


So the minor corrections removed all warnings. Now lets do some extra activities for fun.



  1. Create assembler listing
  2. Type gcc -S hello.c this outputs hello.s
            .file   "hello.c"
    
            .text
    .globl showMessage
            .type   showMessage, @function
    showMessage:
    .LFB0:
            .cfi_startproc
            pushq   %rbp
            .cfi_def_cfa_offset 16
            movq    %rsp, %rbp
            .cfi_offset 6, -16
            .cfi_def_cfa_register 6
            subq    $16, %rsp
            movq    %rdi, -8(%rbp)
            movq    -8(%rbp), %rax
            movq    %rax, %rdi
            call    puts
            leave
            ret
            .cfi_endproc
    .LFE0:
            .size   showMessage, .-showMessage
            .section        .rodata
    .LC0:
            .string "Hello World"
            .text
    .globl main
            .type   main, @function
    main:
    .LFB1:
            .cfi_startproc
            pushq   %rbp
            .cfi_def_cfa_offset 16
            movq    %rsp, %rbp
            .cfi_offset 6, -16
            .cfi_def_cfa_register 6
            movl    $.LC0, %edi
            call    showMessage
            movl    $0, %eax
            leave
            ret
            .cfi_endproc
    .LFE1:
            .size   main, .-main
            .ident  "GCC: (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5"
            .section        .note.GNU-stack,"",@progbits
    
    
    The assembler file is one reason most programmers (run away) do not like assembly language! ha ha. Unless of course if the paying job calls for using assmbly (or assembler) langauge. ! But this feature of the gcc to ouput assembler will come in handy when we program a Forth language translator.
  3. Seek help in using gcc
  4. Try man gcc. You will get an eyeful to the useful flags. Better yet, try the free forums or buy a book specifically on the gcc.

No comments:

Post a Comment