Reach for c99-gcc when you need GCC to actually behave like a C99 compiler instead of defaulting to its usual GNU dialect. You will compile and run a small C99 program, see what the wrapper adds on top of plain gcc, and verify the 1999 standard is really in force. Allow about ten minutes if GCC is already installed. The commands below were checked against the Ubuntu GCC 13.3.0 package.
c99 is an alias for c99-gcc on this system. Unless you supply one of the accepted spellings for the same standard, the wrapper calls GCC with -std=c99. That is the whole point of it: GCC 13's own default is a GNU dialect, not C99.
$ command -v c99
/usr/bin/c99
$ readlink -f /usr/bin/c99
/usr/bin/c99-gcc
$ gcc --version | head -1
gcc (Ubuntu 13.3.0-6ubuntu2~24.04.1) 13.3.0
No config file to edit, no service to restart. Compiling is normally unprivileged work; only reach for sudo to install the package or to read a source directory your account cannot reach.
Create or pick a source file ending in .c. This example uses a scratch directory so it cannot clobber a real project file:
$ mkdir -p /tmp/c99-example
$ cd /tmp/c99-example
$ cat > hello.c <<'EOF'
#include <stdio.h>
int main(void)
{
int values[] = { 2, 4, 6, 8 };
size_t count = sizeof values / sizeof values[0];
printf("%zu values\n", count);
return 0;
}
EOF
$ c99 -Wall -Wextra -pedantic-errors hello.c -o hello
$ ./hello
4 values
-Wall and -Wextra switch on useful warning groups. -pedantic-errors turns diagnostics the selected ISO mode requires into hard errors. None of that proves the program is correct, and none of it replaces tests.
Checkpoint: The command finishes with exit status zero, creates an executable named hello, and prints 4 values. Only want an object file for a later link step? Add -c:
$ c99 -Wall -Wextra -pedantic-errors -c hello.c -o hello.o
$ file hello.o
hello.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), ...
The C standard exposes its own version through __STDC_VERSION__; for C99, GCC reports 199901L. Drop a short probe into a separate file, or check an existing build with the preprocessor:
$ printf '%s\n' '#if __STDC_VERSION__ != 199901L' '#error not compiling as C99' '#endif' > c99-check.c
$ printf '%s\n' 'int main(void) { return 0; }' >> c99-check.c
$ c99 -pedantic-errors -c c99-check.c -o c99-check.o
$ echo $?
0
The wrapper already sets the mode for you, so this explicit check earns its keep mostly in a build or test that might one day call a different compiler command instead. A successful compile only confirms this one invocation selected C99; it says nothing about every library or platform detail.
The wrapper accepts -std=c99, -std=c9x and -std=iso9899:1999 as equivalent requests, and it rejects both a different -std=... value and -ansi, since those ask for a different dialect entirely:
$ c99 -std=c99 -pedantic-errors -c hello.c -o hello.o
$ c99 -std=c11 -c hello.c -o hello.o
c99 called with non ISO C99 option -std=c11
$ echo $?
1
Do not try to bend this command into a C11 or C23 compiler by bolting on another standard option. Use gcc -std=c11, or whatever compiler command your project actually names, when a newer dialect is required, and keep that choice visible in the build configuration rather than buried in a developer's shell alias.
The manpage also documents -D_ANSI_SOURCE. That is a preprocessor definition, not a replacement for the wrapper's C99 selection. Add it only when the source or platform documentation specifically calls for it:
$ c99 -D_ANSI_SOURCE -Wall -Wextra -pedantic-errors hello.c -o hello
$ ./hello
4 values
When a compile fails, read the first diagnostic at its original source location before you start changing flags. Because c99 is a shell wrapper around GCC, diagnostics get prefixed with cc: on systems whose underlying compiler uses that name. A non-zero status means nothing you built should be run.
Use -c while you investigate syntax, types and warnings. That separates compiling from linking, so a missing library or unresolved symbol never masks a source-language problem:
$ c99 -Wall -Wextra -pedantic-errors -c source.c -o source.o
$ echo $?
0
If GCC cannot open the file at all, check the path and permissions:
$ test -r /path/to/source.c && echo readable
$ ls -l /path/to/source.c
Redirection and output options can quietly overwrite files. Before replacing an existing executable, build to a new name like hello.new, test it, and only then mv it into place. If a failed build leaves a stray object or executable in your scratch directory, delete that generated file; never delete the source as a shortcut cleanup.
c99 resolves to the installed c99-gcc wrapper.-Wall -Wextra -pedantic-errors and behaved as expected.__STDC_VERSION__ reported the C99 value 199901L.-std=c11 and -ansi are rejected by this wrapper.