In the last post I explained what happens during compilation of a C program, there I explained all 4 stages of compilation as below:
- Preprocessing
- Compilation
- Assembly
- Linking
Apart from compilation errors, there can be runtime errors.
NOTE: Runtime error is a kind of error which will be seen only when you run the program. This means, there was no error reported during compilation time.
In this post I will cover all different kinds of errors that you may face during compiling a C program. Any runtime errors such as segmentation fault, will be covered in a later post.
Let’s start with one by one.
Contents
- 1 Preprocessor Errors
- 2 Compilation Errors
- 3 Assembly errors
- 4 Linker errors
- 5 This is not the end
- 6 Got a question or have a doubt?
Preprocessor Errors
Any statement that start with a “#” is processed by the preprocessor.
Preprocessor can have the below directives:
- #include
- #define
- #if, #elif, #else
- #ifdef, #ifndef
- #error
Let’s cover one by one with example.
#include errors
#include is used to include a header file typically found with .h extension.
You may wonder, where does this header file comes from or where is it located in the filesystem?
I am using MacOS 26.0.1 while writing this post, so for me, the header files are coming from the below location:
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include
If the filename in the #include statement is missing in the configured include path then it will report error.
I wrote a program as below to show you what kind of #include error you may get:
#include <stdi.h>
int main ()
{
printf ("1.4 Errors and Fixes during compilation.");
return 0;
}
I have added stdi.h file to be included in the first line, which does not exist.
As the file is not available, when I ran gcc, I got the below error:
sibsahu@SIBSAHU-M-92Q2 Module-1 % gcc 1.4-errors-and-fix.c
1.4-errors-and-fix.c:1:10: fatal error: 'stdi.h' file not found
1 | #include <stdi.h>
| ^~~~~~~~
1 error generated.
How to fix #include error
This is quite self explanatory and easy to fix.
Below is the error line:
1.4-errors-and-fix.c:1:10: fatal error: 'stdi.h' file not found
It says, in your code file line number 1 and position 10 which starts with “<” has an error.
What is the error:
fatal error: 'stdi.h' file not found
This means, the filename “stdi.h” does not exist in the included path.
To fix this error, either include the path which has this file, or if it is a typo while adding the filename, change the filename to the correct one.
#define errors
There may not be any direct errors caused by #define which can be caught during preprocessing.
The reason is simple. Whatever macro you define through the #define statement will be correctly replaced during the preprocessing phase.
So, if you have introduced a typo, like missed a character from the macro, or if you have missed to define the value for a macro, then these errors will not be caught by preprocessor, rather that’s an error generated from the compilation stage.
Typo in using the macro name
Let’s look at the below demo code:
#include <stdio.h>
#define NUMBER 1
int main ()
{
printf ("%d is the number", NUMBE);
return 0;
}
You can see that I have declared NUMBER as a macro but I have used NUMBE as the variable name for %d in the printf statement.
So, during the preprocessing phase, the preprocessor did not find any NUMBER macro hence nowhere it has replaced the NUMBER with the value 1.
Let’s see what happens when you compile the above code, this will be the error
1.4-errors-and-fix.c:7:33: error: use of undeclared identifier 'NUMBE'
7 | printf ("%d is the number", NUMBE);
| ^
1 error generated.
Undeclared identifier means, the variable name is not declared in your C code. This error is a symantic error and it is not a preprocessor error.
If you have missed to place value in #define macro
Now let’s look at a very common error.
This may be in your program and you might be thinking you have already declared NUMBER but then why do you still see the error in compilation!
#include <stdio.h>
#define NUMBER
int main ()
{
printf ("%d is the number", NUMBER);
return 0;
}
I have declared a macro NUMBER, but I have not given a value to it.
You will see below error in this case:
1.4-errors-and-fix.c:7:33: error: expected expression
7 | printf ("%d is the number", NUMBER);
| ^
1 error generated.
What happens, when this macro is placed, the preprocessor will replace the NUMBER with a white space ” “.
So, the above code will become like this:
#include <stdio.h>
#define NUMBER
int main ()
{
printf ("%d is the number", );
return 0;
}
This code will generate the exact same error as above:
1.4-errors-and-fix.c:7:33: error: expected expression
7 | printf ("%d is the number", );
| ^
1 error generated.
If you see closely the error is generated at the closing parenthesis “)”. The reason for this is, the compiler was expecting a variable identifier but it encountered the closing parenthesis.
This kind of error is actually syntax error or more appropriately grammar violation. These will not fall under symantic errors.
Think of this like in English grammar, you have to use proper article such as a, an or the in front of an object. This is the basic rule. If you add improper article, that would become a grammatical error.
Exactly the same would be considered here.
So, the problem went like this:
- You missed to add a value to the macro or you added a typo in the macro name
- Either preprocessor replaced the macro with a white space or the macro name became different hence compiler thinks that’s a different variable now.
- When the printf statement expects an integer value at %d, and the correct value or the variable is not there, the compiler generated an error.
How to fix #define errors
Identify if you have missed to place a value for the macro or the macro name has a typo.
Based on the finding, fix the issue.
#if, #elif, #else errors
These preprocessor directives may be used like below:
1:
#if SOME_MACRO
// add some include file or declare a variable etc.
#endif
2:
#if SOME_MACRO
// add some include file
// or declare a variable etc.
#else
// some other includes or variable declarations etc.
#endif
3:
#if SOME_MACRO
// add some include file or declare a variable etc.
#elif SOME_OTHER_MACRO
// some includes or variable declarations etc.
#else
// default includes or variable declarations etc.
#endif
Based on the code above, any errors introduced because of these #if will be again indirect just like the #define errors.
Meaning, if the proper header files are not included or appropriate variables are not declared as per the condition, the missing things will be reported as error by the compiler at a later part of the program where these variables or file content are expected.
How to fix #if, #elif, #else errors
This fix is similar to the fix for a #define error.
Find out where the error is reported. If the root of the error falls under any of these #if statement, then examine all the macro definitions properly.
Based on the finding, fix the issue.
You can use #error statement to test if the preprocessor reaches to the #if, #elif, or #else statement or not. If the preprocessor does not report an error where #error is declared, then know that it is not going inside the respective #if or #else statement.
#ifdef, #ifndef erros
These errors are similar to the above #if error.
#ifdef expects a macro to be defined earlier and based on that it will add or remove the statements enclosed under this condition.
Example:
#ifdef HI
#define HELLO "Hello"
#endif
If you are using the HELLO macro somewhere in your program let’s say like this:
printf ("Say %s", HELLO);
then HELLO will be printed if HI is already defined. If HI is not defined earlier, then this HELLO macro will also be not defined and the compiler will report and error at HELLO.
How to fix #ifdef errors
Sometime, the placement of #ifdef needs to be changed in order to fix #ifdef errors.
For example: if HI is defined later but you are declaring HELLO earlier based on declaration of HI, then that would be an error.
Look at the below code:
#include <stdio.h>
#ifdef HI
HELLO "Hello"
#endif
int main ()
{
printf ("Say "%s", HELLO);
}
#define HI
When you compile this file, it will report and error of expected expression where HELLO is used.
To the human eye it may look like HI is defined, and based on that HELLO will be defined.
But in reality, the preprocessor goes from top to bottom. In this sequence when the preprocessor checks if HI is defined, it finds it is actually not yet defined. Hence it will not declare HELLO.
To fix the issue, you need to declare HI before the #ifdef statement.
#include <stdio.h>
#define HI
#ifdef HI
HELLO "Hello"
#endif
int main ()
{
printf ("Say "%s", HELLO);
}
In bigger programs, you have to go through the code to find out where the #defines are added and move the required #define appropriately.
You can use #error statement to test if the preprocessor reaches to the #ifdef or not. If the preprocessor does not report an error where #error is declared, then know that it is not going inside #ifdef statement.
#error errors
When you declare a #error statement the preprocessor will generate an error there.
See the example of #error statement:
#ifndef VERSION
#error "VERSION is not defined. Please define it before compiling."
#endif
Main purpose of this #error declaration is to raise error at preprocessor stage if some compilation flags or other macro definations are not defined or configured properly.
If you compile the above code with gcc -DVERSION, then this will not report any error, otherwise it will.
As I mentioned earlier, the #error can be used to debug preprocessor conditional statements like #if, #else, #ifdef etc.
#error "Checking the #if"
#error "Checking the #elif"
#error "Checking the #else"
#error "Checking ifdef HI"
etc.
How to fix #error errors
Mainly in production code, #error codes are included in places which are like mandatory configuration macro declarations.
Either these macros are defined within any c or header file or they are coming from the compiler flag as I have shown earlier.
Based on the error, find from where does the macro definition comes and declare it appropriately.
Compilation Errors
Compilation errors are mostly related to grammatical errors, such as missing semicolon, misplaced parenthesis or curly brace etc.
This may have a big list of errors but let’s start with one by one and I will keep adding once I come across with a new error.
Below is a list of compilation errors (as of now this is a minimal list of errors):
- error: expected ‘;’ after expression
- error: use of undeclared identifier error
- error: expected identifier or ‘(‘
- This is similar to the previous error
- error: expected expression
- error: expected function body after function declarator
- error: extraneous closing brace (‘}’)
- and many more …
error: expected ‘;’ after expression
This is a very common error when you are beginning with C programming.
Every statement in C ends with a semicolon. If you have missed one, then this error will be reported.
printf ("%d is the number", NUMBER)
If you compile the c program having the above line of code without ending with semicolon “;” then this error will come from compiler.
How to fix expected ‘;’ after expression
Identify the line number and add a semicolon at the appropriate place.
error: use of undeclared identifier error
An identifier is a name given to a variable, macro or array etc by the user.
For example: int number, char ch, etc. where number and ch are identifiers.
Look at the below piece of code:
int number;
printf ( "Value of number is %d", numbe );
Here, I have declared number as an integer but I am using numbe in the printf statement which is not declared anywhere.
In this case the compiler is looking for numbe variable which is not defined anywhere, hence it throws the error: use of undeclared identifier.
How to fix undeclared identifier error
Identify the line number at which the compiler generated an error. Examine the respective variable name expected and fix it if there is a typo.
error: expected expression
This error comes when you are calling a function which expects several arguments but you are not passing all of them.
Look at the below line of code:
printf ("Today's date is %d" );
In the above printf() statement I have added a “%d” which expects an integer to be used, but I have not provided any integer variable in the arguments.
In this case the compiler will generate error: expected expression.
How to fix error: expected expression
Identify the line of error and position from where the error is being reported by the compiler.
Based on the location of the error, add the relevant variable.
error: expected function body after function declarator
A function definition should look with something like this:
int function ()
{
printf (" Some print");
}
If you have missed the starting curly brace then the compiler will report the error: expected function body after function declarator at the starting of printf statement.
Example code will be like this:
int function ()
printf (" Some print ");
}
After the function () the compiler was expecting a starting curly bracket.
In a program of 100s or 1000s of lines or more, this kind of error may happen.
Expected fix
Observe the line number and position in the line. If this is a statement and if there is a starting curly brace was expected for a starting of function, before or around the error, then add it.
error: extraneous closing brace (‘}’)
In the above example of code where I intentionally left the starting curly brace, you notice the that the closing curly brace is still there.
In that case, the compiler thinks that this is an extra curly brace added here.
NOTE: this error comes only if an extra closing curly brace is added or the opening curly brace is left out. This error does NOT come if you have an extra curly brace at the beginning.
Assembly errors
Of course there can be some assembly errors one may encounter while compiling a C program.
But, I do not recount of encountering any assembler errors.
The compilation stage takes care of ruling out all syntax and grammatical errors from a C program.
It is likely to face assembler errors in very big projects here the compilation is related to hardware or architecture specific such as cross compilation.
Mainly these kind of errors may rise because of missing architecture specific compiler flags.
Most likely, you will not face any assembler errors in normal day to day C programming learning.
Linker errors
When you write all instructions corerrectly then the compilation stage will go successfully.
In a case where you have declared a variable is externally defined in other header file, then that variable will only be checked at linking stage.
or,
If you are calling a function and you have not added the header file that defines the syntax of the function.
or,
If you have declared a static variable in let’s say file1.c and accessing the same variable name in file2.c by declaring extern, will not work because by design, static can only be accessible locally in a single file.
For example, look at the below code:
#include <stdio.h>
extern int num;
int main ()
{
printf ("%d is the number", num);
return 0;
}
When you compile the above code, you will get errors like this on Linux:
$ gcc 1-extern-static-linking.c
/tmp/ccbQLhD9.o: In function `main':
1-extern-static-linking.c:(.text+0x6): undefined reference to `num'
collect2: error: ld returned 1 exit status
Or this error on Mac OS:
% gcc 1.4-errors-and-fix.c
Undefined symbols for architecture arm64:
"_num", referenced from:
_main in 1-a0c9e0.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
This error is coming from the “ld” utility which is the linker.
How to fix linker errors
Linker error tells that this variable or function or the symbol is not declared in the current of c code compilation.
Ideal fix would be to find out where exactly the variable or function is defined.
- Include the correct header where the declaration of the variable or function is present
- If a variable is defined in a c file. Try to move it to a common header file
- See if you have made a typo while using the variable name.
This is not the end
There can be many kinds of errors one may face during compilation.
Once you look at the error message, line number, position of occurrence etc. it is pretty easy to fix these compilation errors.
In fact, these compilation errors will help you learn basic grammatical rules of C, syntax, and how to write clean code.
Got a question or have a doubt?
I have tried to cover all common compiler errors in this post but keep in mind that some errors are still missing. I will keep adding all different kinds of errors slowly one by one.
As a beginner or a student, sometimes understanding compiler errors is difficult.
If you find difficulties understanding any compiler error or a warning message or if you just want to understand the reason behind the compiler behavior, I invite you to sign up and use the respective forum for compilation discussions and create a topic with all the details.
Below are the useful links when you think you need help in learning C: