Should I use "-ansi" or explicit "-std=..." as compiler flags? - c

I've read that ANSI C is not exactly the same as ISO C and compilers may differ in interpretation of what "-ansi" is about. (gcc maps it to C90, clang maps it to C89) At the moment I would tend to use "-std=..." over "-ansi" as then it is explicitly shown which standard is used. As I am specifically interested in compiling on Linux, Windows and MAC, I fear some compilers could not understand "-std=..." but "-ansi". So are there any pros and cons for using the one over the other?

If you want the compiler to enforce the 1989 ANSI C standard, or equivalently the 1990 ISO C standard (they describe exactly the same language), you can safely use either -ansi or -std=c89.
The name -ansi is, strictly speaking, incorrect; it refers to the 1989 ANSI C standard, but ANSI itself considers that standard to be obsolete; it was replaced by the 1999 ISO C standard (which ANSI officially adopted shortly after it was released) which itself either has been, or soon will be, replaced by the new 2011 ISO C standard. But changing the meaning of the -ansi option would break too many Makefiles and build scripts.
The gcc 4.7 and later versions also recognize -std=c90 as a synonym for -std=c89. gcc 4.7 was released in March 2012, so -std=c90 is reasonably portable unless you need to allow for older versions of gcc.
-std=c99 enforces (most of) the 1999 ISO C standard. Since Microsoft in particular doesn't support C99 (even after all these years), using this option means the compiler won't warn you about use of C99-specific features that might not be supported elsewhere. gcc's C99 support is documented here.
gcc 4.7 has partial support for the new ISO C 2011 standard, with -std=c11. That support has improved in later releases, but is not yet complete. gcc C11 status is documented here, and is said to be similar to the level of C99 support.
There are more options, and a number of aliases for the ones I've mentioned; for example, the option -std=c9x was added before the 1999 ISO standard was finalized, and it's still supported; similarly, -std=c1x is a synonym for -std=c11.
I believe that clang is intended to be as compatible as possible with gcc, so it should support the same options with the same meanings (except perhaps for some of the newer ones, depending on which versions of gcc and clang you're using).
The gcc manual has the full details, with one section describing the supported standards and another specifying the various -ansi and -std=... options. The links are to the 4.7 version. You can also run info gcc (if you have the GNU info command and the gcc documentation installed), or you can see multiple versions of the manual here.
If you're going to use compilers other than gcc (and compilers that aim to be gcc-compatible), you'll have to read their documentation to find out how to enforce various versions of the C standard.

-ansi and -std= compiler flags may be shared by other compilers but they are gcc flags.
As of now -ansi is equivalent to -std=c89 in gcc but this may1) change in the future so I suggest you to use -std=c89 over -ansi. Indeed ISO c99 for example has also been ratified by ANSI.
You should note that c89 and c90 are essentially the same C Standard. c89 is the ANSI name while c90 is the ISO name.
From gcc page:
There were no technical differences between these publications, although the sections of the ANSI standard were renumbered and became clauses in the ISO standard. This standard, in both its forms, is commonly known as C89, or occasionally as C90, from the dates of ratification.
1) As noted by Keith Thompson in the comments, even though it's probably unlikely as it would break many build scripts.

Related

language standard version versus compiler version

What is the difference between the C version (e.g. C99) and the C compiler version (e.g. 4.9.3)
$ ./arm-none-eabi-gcc --version
arm-none-eabi-gcc (GNU Tools for ARM Embedded Processors) 4.9.3 20150529 (release) [ARM/embedded-4_9-branch revision 227977 with DYNAMIC_REENT by Ambarella]
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
How can I tell whether I am using at least C99 so that I may take advantage of certain macros.
C version is the name of the C standard.
Major standards in historical order:
K&R
ANSI (aka C89 for ANSI, and C90 for ISO)
C99
C11
As the C language has evolved during the last 40 years — new or amended features were introduced in those standards.
gcc compiler version - is just the version of the software. Older versions may not support newer C standards. You can inform the compiler what standard your code conforms to using command line options:
2.1 C Language
The original ANSI C standard (X3.159-1989) was ratified in 1989 and
published in 1990. This standard was ratified as an ISO standard
(ISO/IEC 9899:1990) later in 1990. There were no technical differences
between these publications, although the sections of the ANSI standard
were renumbered and became clauses in the ISO standard. The ANSI
standard, but not the ISO standard, also came with a Rationale
document. This standard, in both its forms, is commonly known as C89,
or occasionally as C90, from the dates of ratification. To select this
standard in GCC, use one of the options -ansi, -std=c90 or
-std=iso9899:1990; to obtain all the diagnostics required by the standard, you should also specify -pedantic (or -pedantic-errors if
you want them to be errors rather than warnings). See Options
Controlling C Dialect.
Errors in the 1990 ISO C standard were corrected in two Technical
Corrigenda published in 1994 and 1996. GCC does not support the
uncorrected version.
An amendment to the 1990 standard was published in 1995. This
amendment added digraphs and __STDC_VERSION__ to the language, but
otherwise concerned the library. This amendment is commonly known as
AMD1; the amended standard is sometimes known as C94 or C95. To select
this standard in GCC, use the option -std=iso9899:199409 (with, as for
other standard versions, -pedantic to receive all required
diagnostics).
A new edition of the ISO C standard was published in 1999 as ISO/IEC
9899:1999, and is commonly known as C99. (While in development, drafts
of this standard version were referred to as C9X.) GCC has
substantially complete support for this standard version; see
http://gcc.gnu.org/c99status.html for details. To select this
standard, use -std=c99 or -std=iso9899:1999.
Errors in the 1999 ISO C standard were corrected in three Technical
Corrigenda published in 2001, 2004 and 2007. GCC does not support the
uncorrected version.
A fourth version of the C standard, known as C11, was published in
2011 as ISO/IEC 9899:2011. (While in development, drafts of this
standard version were referred to as C1X.) GCC has substantially
complete support for this standard, enabled with -std=c11 or
-std=iso9899:2011. A version with corrections integrated is known as C17 and is supported with -std=c17 or -std=iso9899:2017; the
corrections are also applied with -std=c11, and the only difference
between the options is the value of __STDC_VERSION__.
By default, GCC provides some extensions to the C language that, on
rare occasions conflict with the C standard. See Extensions to the C
Language Family. Some features that are part of the C99 standard are
accepted as extensions in C90 mode, and some features that are part of
the C11 standard are accepted as extensions in C90 and C99 modes. Use
of the -std options listed above disables these extensions where they
conflict with the C standard version selected. You may also select an
extended version of the C language explicitly with -std=gnu90 (for C90
with GNU extensions), -std=gnu99 (for C99 with GNU extensions) or
-std=gnu11 (for C11 with GNU extensions).
The default, if no C language dialect options are given, is
-std=gnu11.
The ISO C standard defines (in clause 4) two classes of conforming
implementation. A conforming hosted implementation supports the whole
standard including all the library facilities; a conforming
freestanding implementation is only required to provide certain
library facilities: those in <float.h>, <limits.h>, <stdarg.h>, and
<stddef.h>; since AMD1, also those in <iso646.h>; since C99, also
those in <stdbool.h> and <stdint.h>; and since C11, also those in
<stdalign.h> and <stdnoreturn.h>. In addition, complex types, added in
C99, are not required for freestanding implementations.
The standard also defines two environments for programs: a
freestanding environment, required of all implementations and which
may not have library facilities beyond those required of freestanding
implementations, where the handling of program startup and termination
are implementation-defined; and a hosted environment, which is not
required, in which all the library facilities are provided and startup
is through a function int main (void) or int main (int, char *[]). An
OS kernel is an example of a program running in a freestanding
environment; a program using the facilities of an operating system is
an example of a program running in a hosted environment.
GCC aims towards being usable as a conforming freestanding
implementation, or as the compiler for a conforming hosted
implementation. By default, it acts as the compiler for a hosted
implementation, defining __STDC_HOSTED__ as 1 and presuming that when
the names of ISO C functions are used, they have the semantics defined
in the standard. To make it act as a conforming freestanding
implementation for a freestanding environment, use the option
-ffreestanding; it then defines __STDC_HOSTED__ to 0 and does not make assumptions about the meanings of function names from the standard
library, with exceptions noted below. To build an OS kernel, you may
well still need to make your own arrangements for linking and startup.
See Options Controlling C Dialect.
GCC does not provide the library facilities required only of hosted
implementations, nor yet all the facilities required by C99 of
freestanding implementations on all platforms. To use the facilities
of a hosted environment, you need to find them elsewhere (for example,
in the GNU C library). See Standard Libraries.
Most of the compiler support routines used by GCC are present in
libgcc, but there are a few exceptions. GCC requires the freestanding
environment provide memcpy, memmove, memset and memcmp. Finally, if
__builtin_trap is used, and the target does not implement the trap pattern, then GCC emits a call to abort.
For references to Technical Corrigenda, Rationale documents and
information concerning the history of C that is available online, see
http://gcc.gnu.org/readings.html

How can some GCC compilers modify a constant char pointer?

I am reading a book titled "Understanding and Using C pointers".
On page 110, it had these lines:
... However, in some compilers, such as GCC, modification of the string literal is possible. Consider the following example:
char *tabheader = "Sound";
*tabheader = 'L';
printf("%s\n", tabheader); //Displays "Lound"
It goes on and describe the usage of const char *tabheader which will prevent from modifying this variable.
I am currently using Cloud 9/Ubuntu. I compiled this code using GCC and ran it. It caused segmentation fault error as I expected.
I am very perplexed with these statements in the book.
All this time, my understanding of the statement char *tabheader = "Sound"; is same as const char *tabHeader = "Sound"; Now, this book is saying that is dependent on which gcc compiler
My question is this: Which GCC compiler allows this code to run?
What is your opinion on this?
Does this also belong to undefined behavior?
This would work in versions of GCC prior to 4.0 if you use the -fwritable-strings option when compiling. This option was removed in 4.0.
It would work on systems that don't store string literals in a protected part of memory. For example, the AVR port of GCC stores string literals in RAM and all RAM is writable, so you can probably write to them. In general, writing to a string literal is undefined behavior so you should not do it.
You mentioned you were confused about the difference between these two lines:
char *tabheader = "Sound";
const char *tabHeader = "Sound";
The main difference is that with the const qualifier, the compiler knows at compile time that you cannot write to the string so it will give you errors at compile time instead of undefined behavior at run time if you try to write to it.
gcc has many modes and compatibilities. Originally (1970s) in C, there was no const type and certainly no concept that a string literal was constant. It was occasional (but infrequent) practice in those days to use a string literal as a buffer initialization.
The eventual and slow evolution of string literals to being implied constants has caused pain with maintenance of ancient code which depends on earlier behavior. Gcc's philosophy apparently enables old behavior with a compiler flag. For example, from man gcc for gcc 6.3.1 20161221 (Red Hat 6.3.1-1), the section on -std is (partially):
-std=
Determine the language standard. This option is currently only
supported when compiling C or C++.
The compiler can accept several base standards, such as c90 or
c++98, and GNU dialects of those standards, such as gnu90 or
gnu++98. When a base standard is specified, the compiler accepts
all programs following that standard plus those using GNU
extensions that do not contradict it. For example, -std=c90 turns
off certain features of GCC that are incompatible with ISO C90,
such as the "asm" and "typeof" keywords, but not other GNU
extensions that do not have a meaning in ISO C90, such as omitting
the middle term of a "?:" expression. On the other hand, when a GNU
dialect of a standard is specified, all features supported by the
compiler are enabled, even when those features change the meaning
of the base standard. As a result, some strict-conforming programs
may be rejected. The particular standard is used by -Wpedantic to
identify which features are GNU extensions given that version of
the standard. For example -std=gnu90 -Wpedantic warns about C++
style // comments, while -std=gnu99 -Wpedantic does not.
A value for this option must be provided; possible values are
c90
c89
iso9899:1990
Support all ISO C90 programs (certain GNU extensions that
conflict with ISO C90 are disabled). Same as -ansi for C code.
iso9899:199409
ISO C90 as modified in amendment 1.
c99
c9x
iso9899:1999
iso9899:199x
ISO C99. This standard is substantially completely supported,
modulo bugs and floating-point issues (mainly but not entirely
relating to optional C99 features from Annexes F and G). See
<http://gcc.gnu.org/c99status.html> for more information. The
names c9x and iso9899:199x are deprecated.
c11
c1x
iso9899:2011
ISO C11, the 2011 revision of the ISO C standard. This
standard is substantially completely supported, modulo bugs,
floating-point issues (mainly but not entirely relating to
optional C11 features from Annexes F and G) and the optional
Annexes K (Bounds-checking interfaces) and L (Analyzability).
The name c1x is deprecated.
gnu90
gnu89
GNU dialect of ISO C90 (including some C99 features).
gnu99
gnu9x
GNU dialect of ISO C99. The name gnu9x is deprecated.
gnu11
gnu1x
GNU dialect of ISO C11. This is the default for C code. The
name gnu1x is deprecated.
c++98
c++03
The 1998 ISO C++ standard plus the 2003 technical corrigendum
and some additional defect reports. Same as -ansi for C++ code.
gnu++98
gnu++03
GNU dialect of -std=c++98.
c++11
c++0x
The 2011 ISO C++ standard plus amendments. The name c++0x is
deprecated.
gnu++11
gnu++0x
GNU dialect of -std=c++11. The name gnu++0x is deprecated.
c++14
c++1y
The 2014 ISO C++ standard plus amendments. The name c++1y is
deprecated.
...
Note that there are other compiler flags which control acceptance or rejection or alternate handling of K&R function headers and similar aspects.

What is the difference between the "c99" and "gcc" commands with appropriate flags?

Up until today I always read on the Internet how gcc is the best compiler for C (at least for the student level of programing, followed closely by Clang).
However in "21st Century C" Mr Ben Klemens suggests that c99 is better(?) than running gcc -std=c99 (actual line is [page 11]: everybody else switched to C99 being the default a long
time ago...)
I wasn't able to find anything on the subject of c99 compiler, so my question is:
Is there any difference between those commands and if there are, which one is better?
EDIT: The standard C99 is clearly metioned in the paragraph, however from the beginning the suggested method of compiling is the command:
gcc erf.c -o erf -lm -g -Wall -O3 -std=gnu11
However on page 11 the author states:
The POSIX standard specifies that c99 be present on your system, so the
compiler-agnostic version of the above line would be:
c99 erf.c -o erf -lm -g -Wall -O3
This seems to suggest there is a difference in those 2 commands. I wasn't able to find any additional info nor was it clear to me from the text, what the second line is exactly (no man page for c99 on my Cygwin either).
C99 is the 1999 edition of the ISO C standard. It replaced the 1990 standard, and has been (officially, at least) replaced by the 2011 standard.
What you're asking about, though, is the c99 command (I've updated your question's title to clarify that).
POSIX specifies a c99 command. The requirements are documented here. It is "an interface to the standard C compilation system".
On typical Linux systems, the c99 command /usr/bin/c99 is a small shell script that invokes the gcc commmand. It invokes gcc with the -std=c99 option. It also checks whether the user has already specified an equivalent option, so it doesn't use the same option twice. If an incompatible option has been given, such as c99 -std=c90, it terminates with an error message.
Given such an implementation, the command
c99 [args]
is exactly equivalent to
gcc -std=c99 [args]
As I mentioned above, the C99 standard has been officially superseded by the C11 standard. gcc version 5 (the current latest release is 5.3.1) has reasonably good support but not 100% complete support for C11. POSIX has not (yet) specified a c11 command.
There's nothing wrong with using the C99 standard if you don't need C11-specific features -- or even the C90 standard if you don't need C99-specific features.
In my PDF copy of the book, the discussion about using c99 instead of gcc -std=c99 seems to be on page 10, not 11.
And what is being discussed is not that c99 is "better" than gcc, but that you might be able to more easily use C99-standard compiler features with the c99 command, since you don't then need to know the specific option to enable C99 features or whether the default for the compiler is C99 or C89.
On my system, the command c99 is just an alias or link for gcc that has the -std=c99 set by default (and complains if a non-C99 standard is specified with the -std= option). I imagine that or something similar is true on most systems with a c99 compiler command.
In fact, on my system c99 is a link to a shell script:
#! /bin/sh
# Call the appropriate C compiler with options to accept ANSI/ISO C
# The following options are the same (as of gcc-3.3):
# -std=c99
# -std=c9x
# -std=iso9899:1999
# -std=iso9899:199x
extra_flag=-std=c99
for i; do
case "$i" in
-std=c9[9x]|-std=iso9899:199[9x])
extra_flag=
;;
-std=*|-ansi)
echo >&2 "`basename $0` called with non ISO C99 option $i"
exit 1
;;
esac
done
exec gcc $extra_flag ${1+"$#"}
Try c99 --version on a typical Linux box. You will get the version and name of the compiler which is gcc.
c99 is just a shortcut to the c99 compliant compiler on your machine. That way you don't have to care about the actual compiler used. POSIX also requires some common command line options the compiler has to understand. If that is gcc, it shall enable c99 compliant features. This should be identical to gcc -std=c99.
gcc provides additional features which are enabled by default [1] when called by its native name and by the -std=gccXX option in addition to the CXX standard. For older versions, some of these extensions became part of the next C standard either directly or with slightly different syntax. A typical and appreciated extension for C90 is support for C++-style line-comments:
// this is not allowed in pure C90
For c99/gnu99 things are less obvious, but might still add some usefull features.
On other POSIX systems, e.g. Unix, you may find a different compiler. It shall still be available by the name c99.
Note that the current and only valid C standard is C11 since 2011. So if you want to use the new features (e.g. atomics, thread-support), you have to deviate from the pure POSIX-path. Yet it is likely POSIX might be updated some day.
[1] The default version of the C standard depends on the version of gcc. pre5 used C90, while gcc 5.x uses C11.

How to find out which ANSI C standard my gcc works with by default?

I read here it is C90 with extensions. How can I know for sure?
Try below command and search for std
gcc -v --help | less
It will show you all the available options for your gcc.
Read the manpage. On my computer (OSX 10.7, gcc version 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)):
-std=
Determine the language standard. This option is currently only supported
when compiling C or C++.
A value for this option must be provided; possible values are
....
gnu89
Default, ISO C90 plus GNU extensions (including some C99 features).
....
gnu++98
The same as -std=c++98 plus GNU extensions. This is the default for C++ code.
Use the -std= flag to specify a language dialect: c89, c99, c++98, etc. Note that c90 is equivalent to c89.
As a shorthand -ansi causes -std=c89 in C mode and -std=c++98 in C++ mode.
Use -pedantic to enable all diagnostics that the standards require.
The defaults are gnu89 for C and gnu++98 for C++. Consult the manual for detailed descriptions of the various dialects.
You can also check one of the predefined Macros, for example whether your GCC asks for ANSI C (STRICT__ANSI) by default (i.e. without any cli arguments).
No version of gcc fully conforms to any ANSI or ISO C standard by default. The default is always equivalent to -std=gnuNN, supporting the given standard with GNU-specific extensions. Prior to version 5 (and going back a number of years), the default was -std=gnu90. Starting with version 5, the default is -std=gnu11.
There have been three ISO C standards: C90, C99, and C11. (C95 was a minor amendment to C90.) The first ANSI C standard was published in 1989, and is known as C89; it describes the same language as the ISO C90 standard.
To find out the default language version for the gcc you have running, type
info gcc
search for the phrase "The default".
This assumes that you have the gcc documentation installed, that the documentation shown by info gcc matches the version of gcc you're running, and that the wording is similar enough that searching for "The default" will find the correct information. None of these is guaranteed. Older gcc manuals may be organized differently.
More reliably, run
gcc --version
to see what version you're running, then visit the GCC online documentation page and read the documentation for the version you're running.
More simply, if you have a version before 5.0, the default is -std=gnu89; otherwise the default is -std=gnu11. (That may change in a future release, but only some time after a new ISO C standard is published and the gcc maintainers have had time to implement it and decide to make it the default. Don't hold your breath.)
Or you can avoid the question altogether by specifying the version you want using the -std=... command-line option.

C99 not default C- version for GCC?

Why does not GCC compile the C99 by default? I mean why is it necessary to add --std=c99 flag
everytime a code in C99 is written?
Edit: As of GCC 5, -std=gnu11 is the default. See Porting to GCC 5.
See C Dialect Options, gnu89 is the default.
`gnu89'
GNU dialect of ISO C90 (including some
C99 features). This is the default for
C code.
As #tsv mentioned, ISO C99 is not fully supported yet:
`c99'
`c9x'
`iso9899:1999'
`iso9899:199x'
ISO C99. Note that this standard is not yet fully supported; see http://gcc.gnu.org/c99status.html for more information. The names `c9x' and `iso9899:199x' are deprecated.
And also:
`gnu99'
`gnu9x'
GNU dialect of ISO C99. When ISO C99 is fully implemented in GCC, this will become the default. The name `gnu9x' is deprecated.
Perhaps because it still isn't fully implemented - see C99 status.
It also could be argued C99 features haven't been widely adopted, although that's something of a circular argument.
Use the command c99 to compile C programs.
The current POSIX standard specifies the command c99, so it should be available in most Unix-like systems.
The reason is that default configurations of gcc take a really long time to be changed, since every time a default configuration is changed, it can potentially break the compilation of valid programs (in this case valid c89 programs which are invalid in c99). Starting with gcc 5.0, the default C standard used by gcc will be gnu11, which is c11 with gnu extensions (see here):
The default mode for C is now -std=gnu11 instead of -std=gnu89.

Resources