When writing code we are often moving fast, this can sometimes lead to problems where we make a simple (and sometimes, not so simple) mistake. Thankfully, when you compile with GCC we obtain valuable information on those errors, the follwing is a FAQ that can help you debug those bugs. This FAQ is oriented at issues in the C language.
We will begin with some of the basics, using a simple hello world program.
This is the most common syntax error. Lets review the following code that contains the problem.
1 #include <stdio.h> 2 3 int main() 4 { 5 6 printf("Hello!\r\n"); 7 return 0 8 } 9
When compiling the code, you recieve the following output.
:~$ gcc -o test1 test1.c test1.c: In function 'main': test1.c:8: error: expected ';' before '}' token
Our error states pretty clearly that in the main function, the compiler expects a semicolon before the close bracket. This is a pretty simple example, and not all problems will be as easy to identify. The tricky part is that even though the error says the issue lies on line 8, the semicolon is missing from the return statement on line 7. The line number in the error is not always a direct identifier to the problem, but will help you zero in on it.
1 #include <stdio.h> 2 3 int main() 4 { 5 6 for(x = 1; x < 5; x++) 7 { 8 printf("Hello!\r\n"); 9 } 10 return 0; 11 } 12
Using the following compilation line:
:~$ gcc -o test1 test1.c test1.c: In function 'main': test1.c:6: error: 'x' undeclared (first use in this function) test1.c:6: error: (Each undeclared identifier is reported only once test1.c:6: error: for each function it appears in.)
That's quite a bit of error spam! Not to worry, its pretty simple. Looking at the problem, we see that 'x' is undeclared, and the compiler will only complain about it once per function - so if you used 'x' 30 times in THAT function, you would only get the one error.
Wait, x is set to = 0 right? Yes, it is, but in C (and most other languages) you must declare x as a variable with a type. The following nugget of code solves the problem.
1 #include <stdio.h> 2 3 int main() 4 { 5 int x; 6 for(x = 1; x < 5; x++) 7 { 8 printf("Hello!\r\n"); 9 } 10 return 0; 11 }
We've added “int x;” to line 5, the program will happily compile now as you say hello to the world multiple times.
The GCC compiler is smart enough to figure out where you are going wrong SOMETIMES. I'm not a big fan of it, because it allows you to code incorrectly, and in the end who wants to see warning spam?? Lets look at the code to see where we went wrong.
1 int main() 2 { 3 printf("Hello!\r\n"); 4 return 0; 5 }
It may not be obvious to the novice programmer, but we are missing a header file, stdio.h to be precise. Stdio.h holds all the function definitions for basic input and output (including our pal printf that you so carelessly used without its parent!). Adding the line the following line will rectify the issue though.
1 #include <stdio.h>
Header files can sometimes be a bit tricky, you really need to know where a function is defined, but that is what the interwebs are for, research is your buddy.
1 #include <stdio.h> 2 3 int main() 4 { 5 printf(""Hello!"\r\n"); 6 return 0; 7 }
Results in the error:
~$ gcc -o test1 test1.c test1.c: In function 'main': test1.c:5: error: expected ')' before 'Hello'
Another sticky wicket for the novice. Since quotes are required to output a string or char array, how do we use them IN a string? Simply by using our pal the escape sequence (sounds sci-fi eh?). The fancy sounding term is nothing but the old backslash. To escape a quote for example, you use \“, and the compiler knows that it's not encasing some text, but is part of it.
Here is the fix.
1 #include <stdio.h> 2 3 int main() 4 { 5 printf("\"Hello!\"\r\n"); 6 return 0; 7 }
Which will output “Hello!” encased in quotes. But hey!.. you say. I see other text with the escape! You are correct! the \r and \n are escape sequences for return and newline respectively, one of the benefits of printf is that you can format the string within the string. Woohoo!
There are many other escape sequences as well, here's a list of the more common ones. I highly recommend using \a in long loops.
\a Bell (alert) \b Backspace \f Formfeed \n New line \r Carriage return \t Horizontal tab \v Vertical tab \' Single quotation mark \" Double quotation mark \\ Backslash \? Literal question mark \ooo ASCII character in octal notation \xhh ASCII character in hexadecimal notation
~$ gcc -o test1.c test1 test1:(.rodata+0x0): multiple definition of `_fp_hw' /usr/lib/gcc/i486-linux-gnu/4.1.2/../../../../lib/crt1.o:(.rodata+0x0): first defined here test1: In function `__data_start': (.data+0x4): multiple definition of `__dso_handle' /usr/lib/gcc/i486-linux-gnu/4.1.2/crtbegin.o:(.data+0x0): first defined here test1: In function `_init': /home/aurel32/glibc/glibc-2.3.6.ds1/build-tree/i386-libc/csu/crti.S:36: multiple definition of `_init' /usr/lib/gcc/i486-linux-gnu/4.1.2/../../../../lib/crti.o:/home/aurel32/glibc/glibc-2.3.6.ds1/build-tree/i386-libc/csu/crti.S:36: first defined here test1: In function `_start': ../sysdeps/i386/elf/start.S:65: multiple definition of `_start' /usr/lib/gcc/i486-linux-gnu/4.1.2/../../../../lib/crt1.o:../sysdeps/i386/elf/start.S:65: first defined here test1: In function `_fini': /home/aurel32/glibc/glibc-2.3.6.ds1/build-tree/i386-libc/csu/crti.S:52: multiple definition of `_fini' /usr/lib/gcc/i486-linux-gnu/4.1.2/../../../../lib/crti.o:/home/aurel32/glibc/glibc-2.3.6.ds1/build-tree/i386-libc/csu/crti.S:52: first defined here test1:(.rodata+0x4): multiple definition of `_IO_stdin_used' /usr/lib/gcc/i486-linux-gnu/4.1.2/../../../../lib/crt1.o:(.rodata+0x4): first defined here test1: In function `__data_start': (.data+0x0): multiple definition of `__data_start' /usr/lib/gcc/i486-linux-gnu/4.1.2/../../../../lib/crt1.o:(.data+0x0): first defined here collect2: ld returned 1 exit status
Oh noez! You are going to fail your class!!! .. Actually, this is a simple one.
Instead of typing this to compile your program..
~$ gcc -o test1.c test1
Try putting it the right way :D (destination file name first, followed by the source file)
~$ gcc -o test1 test1.c
What what?? Yes, this was a simple solution, but with an overwhelming error output. Goes to show that the compiler for all it's smarts, still can trip up on simple user i/o problems.