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

Dashboard
Notifications
Mark all as read
Q&A

What compiler options are recommended for beginners learning C?

+11
−0

When reading questions about C programming from beginners, I very often see them describing peculiar run-time errors and crashes, segmentation faults and similar. They have spent a lot of time chasing down the bug but failed.

Then upon viewing their code, I notice that the code should never have "compiled cleanly" - there were warnings, but the beginner didn't read them. If they had done so, it would have saved them a lot of time.

Not reading warnings could in turn be caused by the IDE used, which is hiding away warnings in some hard-to-spot window, or because they picked some "compile & run" option, or simply because they weren't paying attention.

Or possibly because they think that warnings mean "here's a little cosmetic issue that you should fix when you have time", and not "here is a severe bug that will likely prevent your program from working as expected" which is closer to the truth most of the time.

Unfortunately, a compiler isn't required to give an error upon C language violations. A "diagnostic message" is sufficient, as discussed at What must a C compiler do when it finds an error?

Are there any recommended compiler options beginners should use to avoid accidentally running programs with errors already spotted by the compiler?

Mostly interested in the "gcc-like" mainstream compilers: gcc, clang and icc, which have compatible command-line options.

Why does this post require moderator attention?
You might want to add some details to your flag.
Why should this post be closed?

0 comment threads

1 answer

+12
−0

My recommended beginner setup for gcc-like compilers is:

-std=c11 -pedantic-errors -Wall -Wextra -Werror

Here is an explanation of what these options do:

  • -std=c11. gcc & friends are by default set to include non-standard language extensions. These extensions are known as "GNU C" and extensively used in Linux programming in particular.

    However, when learning the language it is important to know what parts that are standard C and what parts that are non-portable compiler extensions. Beginners should focus on learning the C language as specified by the standard ISO 9899, before they move on to learn about various extensions and libraries.

    -std=c11 changes the compiler from using the default "GNU 11" to only use the features specified by the C language standard (ISO 9899:2011).

    There is a newer version of the language called "C17/C18", gcc and clang support it, but icc does not (yet). The differences between C17 and C11 are various detailed, advanced error fixes and nothing that concerns beginners. If you are using gcc or clang, you may as well use -std=c17 though.

  • -pedantic-errors. Together with the -std=c... option above, this forces the compiler into a strict mode. It doesn't mean "whine and be pedantic" as the name implies, but rather "give me diagnostic messages whenever I write invalid C". So this is the most "correct" mode to use when you want to see if your code is valid C or not.

    There's an option -pedantic that gives warnings for invalid C. -pedantic-errors is the same but gives errors and prevents the code from compiling.

  • -Wall doesn't mean "enable all warnings" as one might suspect. It rather means "give me some more warnings that are good to have".

  • -Wextra adds some more warnings still.

  • -Werror turns all warnings into errors and prevents the code from executing until the problems are fixed.


Some other options that may be helpful:

  • -O3 vs -O0. Enable or disable compiler optimizations. If you are concerned about program performance, then you need to use -O3 to enable all optimizations. This might be problematic when you are debugging/troubleshooting though, it's generally recommended to turn optimizations off when debugging. That is done with -O0.

  • -Wunused_result. This warns if you don't check the returned result from a function. Very handy to have but note that this one might get spammy, because most library functions that we commonly use (printf, scanf, strcpy etc) do return a result, which we aren't always interested in. You can cast the result of a function to (void) in case you aren't interested in it - that's good practice, but writing (void) in front of every single printf call might get tedious.

  • -ffreestanding. Always use this if you are compiling for an embedded system, such as a microcontroller application.

  • -fno-strict-aliasing is also strongly recommended for embedded systems, but that's a more advanced topic that I won't address here since this answer is aimed to beginners. (This option might only have an effect on gcc, I believe clang ignores it.)

Do not use:

  • -ansi. There's a common misunderstanding that this enables strict C compilation. It does not, that's -std=c11 -pedantic-errors as explained above. -ansi enables "ANSI C", which is the nickname of the old, obsolete C90 standard, which should be avoided since it comes with a lot of language flaws that have been corrected over the years.
Why does this post require moderator attention?
You might want to add some details to your flag.

2 comment threads

-ansi (3 comments)
Reason for -ansi misunderstanding (1 comment)

Sign up to answer this question »