I am using gcc (Ubuntu 4.4.1-4ubuntu9) to compile a program that I'm writing, but it seems to vomit whenever it sees a // comment in my code, saying:
interface.c :##: error: expected expression before â/â token<
Does the gcc compile mode I'm using forbid // comments?
$ gcc -g -ansi -pedantic interface.c structs.h -c -I. -I/home/me/project/h
Why?
// comments are not allowed in old (pre 99) C versions, use /**/ (or remove the -ansi, that is a synonym for the C89 standard)
See C++ comments in GNU compiler documentation.
In GNU C, you may use C++ style comments, which start with // and continue until the end of the line. Many other C implementations allow such comments, and they are included in the 1999 C standard. However, C++ style comments are not recognized if you specify an -std option specifying a version of ISO C before C99, or -ansi (equivalent to -std=c89).
(Emphasis is mine because some of the posts claim that // are not allowed in standard C whereas that is only true for pre-99 standards).
Related
Given that I know the compiler version:
ANSI C 5.3.0 - GNU C Compiler with options: -lm -lcrypt -O2 -pipe -ansi -DONLINE_JUDGE
How can I know which C standard(C89, C99, C11, C17/18) it adopted If I want to write C program that strictly follows the standard?
How can I know which C standard(C89, C99, C11, C17/18) it adopted
-ansi doesn't mean "give me standard C". It means "give me dinosaur C" and is 100% equivalent to using -std=c89. So if you compiled with -ansi, you are using C89, period.
If you don't use -ansi or -std=... options, then gcc defaults to these versions:
gcc before version 5.0.0 defaults to gnu90.
gcc between version 5.0.0 and up to < 8.0.0 defaults to gnu11.
gcc from 8.0.0 defaults to gnu17.
"gnu" being the C standard + non-standard extensions, in the above cases corresponding to C90, C11 and C17 respectively.
"gnu" mode is not strictly following the standard. In order to do that, you must compile with -std=cxx where xx is your desired version of C. This restricts gcc to a subset only containing standard C features.
But in order to actually make it strict when it comes to reporting compiler errors for invalid use of C, you must do -std=cxx -pedantic-errors.
gcc has a flag that lets you specify the version of the C standard to compile against.
-std=c89 for C89
-std=c99 for C99
-std=c11 for C11
The version you have probably doesn't have support for C17.
There's also:
-std=gnu89 for C89 with GNU extensions
-std=gnu99 for C99 with GNU extensions
-std=gnu11 for C11 with GNU extensions
What is the version of C used in GCC? C99, C11 or C90? I thought was the GCC use C99 but I was mistaken:
for(int i = 0; i < 100; i++){
...
}
error: ‘for’ loop initial declarations are only allowed in C99 mode.
According to 2 Language Standards Supported by GCC:
The default, if no C language dialect options are given, is -std=gnu90; this is intended to change to -std=gnu11 in some future release.
I believe the default is -std=gnu90. You could specify -std=c99 in your compiler flag to support this.
By default gcc uses C90 with GNU extension, this is all covered in the gcc docs Language Standards Supported by GCC, the flag for this would be -std=gnu90:
The default, if no C language dialect options are given, is -std=gnu90; this is intended to change to -std=gnu11 in some future release.
If you want C99 support than you should use -std=c99, although this does not mean gcc will not use extensions, so if you want to receive a warning when gcc using an extension you need to add -pedantic and -pedantic-errors to turn that into an error:
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)
Use -std=99
Before C99, you had to define the local variables at the start of a block. C99 imported the C++ feature that you can intermix local variable definitions with the instructions and you can define variables in the for and while control expressions.
I do include<stdlib.h> where qsort_r is given. And I use gcc -std=c99 -O3 myfun.c -o myfun to compile.
It compiles, links and runs well. I don't know why I got this warning and what is potential risk of this warning ?
BTW, my compiler is gcc version 4.7.3 (Ubuntu/Linaro 4.7.3-1ubuntu1)
It does so because you use -std=c99 , there's no qsort_r function in stdlib.h in c99.
Use -std=gnu99 to make the extensions available, or add a #define _GNU_SOURCE to your source files before including the header files.
qsort_r is not supported by C99. Specification says nothing about it.
Language Standards Supported by GCC:
By default, GCC provides some extensions to the C language that on rare occasions conflict with the C standard1. See Extensions to the C Language Family. Use of the -std options listed above will disable 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=gnu89 (for C89 with GNU extensions) or -std=gnu99 (for C99 with GNU extensions). The default, if no C language dialect options are given, is -std=gnu89; this will change to -std=gnu99 in some future release when the C99 support is complete. Some features that are part of the C99 standard are accepted as extensions in C89 mode.
1. Emphasis is mine
When I ask to see the current version of cc I get this.
$ cc --version
cc (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2
Copyright (C) 2012 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.
$
What I would like to know is which of c89, c90, c99 or c11 is being used.
This is explained in depth in the gcc manual, available (if it's installed) by typing info gcc or online here. The relevant section of the current
manual is here, but it may or may not correspond to the version you're using.
Some of this information has changed since I posted this answer in 2013, and will continue to change. If you're reading this around 2023, the current version is probably -std=gnu17 (C17 with GNU-specific extensions; C17 is a minor update to C11). You should check the documentation for the version you're using. The C23 standard has not yet been released, but should be out Real Soon Now. I can't predict when gcc will switch to -std=gnu23 as its default. If you're reading this in the distant future, let us know how things turned out.
gcc releases from 3.0 to 4.9.4 default to -std=gnu89 or -std=gnu90.
gcc releases from 5.5 to 10.4 default to -std=gnu11 (they skipped -std=gnu99, though you can still specify it).
gcc releases 11.3 and 12.2 default to std=gnu17.
By default, gcc does not conform to any of the ANSI/ISO C standards. The current default is equivalent to -std=gnu17, which is the 2017 standard with GNU-specific extensions. (Some diagnostics required by the language standard are not issued.) Earlier releases of gcc have defaulted to -std=gnu90 or -std=gnu11.
If you want standard conformance, you can use any of the following:
-std=c90 -pedantic
-std=c99 -pedantic
-std=c11 -pedantic
-std=c17 -pedantic
-std=c90 can also be spelled -ansi, -std=c89, or -std=iso9899:1990.
-std=iso9899:199409 supports the C90 standard plus the 1995 amendment, which added a few minor features (all of which are also in C99).
-std=c99 can also be spelled -std=c9x or -std=iso9899:1999 (the name c9x was used before the standard was published). C99 support is not quite complete, but it's close.
-std=c11 can also be spelled -std=c0x or -std=iso9899:2011 (the name c0x was used before the final standard was published; it was wrongly assumed that x would not exceed 9). C11 support is also incomplete; the current status is summarized here.
The -pedantic option causes gcc to print required diagnostics for violations of constraints and syntax rules. In some cases, those diagnostics are merely warnings -- and there's no easy way to distinguish between those warnings and other warnings that aren't required by the language. Replace -pedantic by -pedantic-errors to cause gcc to treat language violations as fatal errors.
A quick history of the standard:
C89 was the first official C standard, published by ANSI in 1989.
C90 was the ISO version of the standard, describing exactly the same language as C89. ANSI officially adopted ISO's version of the standard. There were two Technical Corrigenda, correcting some errors.
C95 was an amendment to C90, adding a few features, mainly digraphs and wide character support. As far as I know, a merged version was never published.
C99 was issued by ISO in 1999. There were three Technical Corrigenda.
C11 was issued by ISO in 2011. There has been one Technical Corrigendum, fixing the definitions of __STDC_VERSION__ and __STDC_LIB_EXT1__.
C17 was issued by ISO in 2017, and was only a minor update to C11.
C23 will be issued in 2023. (As I write this, it's close to being finalized, but the document is still being edited.)
ANSI did not issue its own versions of the 1999 or later standards, adopting the ISO standards instead.
N1256 is a freely available draft of the C99 standard, with the 3 Technical Corrigenda merged into it.
N1570 is a freely available draft of the C11 standard. There are some minor differences between it and the published C11 standard, plus one Technical Corrigendum. For more details, see my answer to this question.
useful information from info gcc for gcc6 and https://gcc.gnu.org/onlinedocs/gcc-5.4.0/gcc/Standards.html#Standards for gcc5
gcc version 6.3.1 - 10.1.0
2.1 C Language
==============
The default, if no C language dialect options are given, is
'-std=gnu11'.
2.2 C++ Language
================
The default, if no C++ language dialect options are given, is
'-std=gnu++14'.
gcc version 5.4.0
2.1 C Language
==============
The default, if no C language dialect options are given, is -std=gnu11
2.2 C++ Language
================
The default, if no C++ language dialect options are given, is -std=gnu++98
For C, default mode remains std=gnu11, but for C++ it has jumped from std=gnu++98 to std=gnu++14
Minimal test program
If you feel like finding it out empirically without reading any manuals.
c.c
#include <stdio.h>
int main(void) {
#ifdef __STDC_VERSION__
printf("__STDC_VERSION__ = %ld \n", __STDC_VERSION__);
#endif
#ifdef __STRICT_ANSI__
puts("__STRICT_ANSI__");
#endif
return 0;
}
Test with:
#!/usr/bin/env bash
for std in c89 c99 c11 c17 gnu89 gnu99 gnu11 gnu17; do
echo $std
gcc -std=$std -o c.out c.c
./c.out
echo
done
echo default
gcc -o c.out c.c
./c.out
Outcome:
c89
__STRICT_ANSI__
c99
__STDC_VERSION__ = 199901
__STRICT_ANSI__
c11
__STDC_VERSION__ = 201112
__STRICT_ANSI__
c17
__STDC_VERSION__ = 201710
__STRICT_ANSI__
gnu89
gnu99
__STDC_VERSION__ = 199901
gnu11
__STDC_VERSION__ = 201112
gnu17
__STDC_VERSION__ = 201710
default
__STDC_VERSION__ = 201710
Conclusion: gnu17 is used by default:
__STRICT_ANSI__: GCC extension that is defined for -std=c but not for -std=gnu, see: https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
__STDC_VERSION__: C99+ ANSI C macro that set for each version. Not present in C89 where it was not yet defined by the standard.
For an explanation of -std=gnu* vs -std=c* see also: What are the differences between -std=c++11 and -std=gnu++11?
C++
main.cpp
#include <iostream>
int main(void) {
#ifdef __cplusplus
std::cout << __cplusplus << std::endl;
#endif
#ifdef __STRICT_ANSI__
std::cout << "__STRICT_ANSI__" << std::endl;
#endif
return 0;
}
Test with:
#!/usr/bin/env bash
for std in c++98 c++11 c++14 c++17 gnu++98 gnu++11 gnu++14 gnu++17; do
echo $std
g++ -std=$std -o cpp.out cpp.cpp
./cpp.out
echo
done
echo default
g++ -o cpp.out cpp.cpp
./cpp.out
Outcome:
c++98
199711
__STRICT_ANSI__
c++11
201103
__STRICT_ANSI__
c++14
201402
__STRICT_ANSI__
c++17
201703
__STRICT_ANSI__
gnu++98
199711
gnu++11
201103
gnu++14
201402
gnu++17
201703
default
201402
Conclusion: gnu++14 is the default:
__cplusplus: macro defined by the C++ standard including on C++98 onwards
Tested on Ubuntu 18.10, GCC 8.2.0. GitHub upstream.
The first line will give your GCC version (4.7.2)
(Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2
When you compile your code, you can specify which C/C++ revision you want to use, by adding -std=c99 or -std=c99 ...
Note gnu89 is used by default.
One thing to be aware of, the -std= option to gcc can not be used to "sandbox" the compiler into not supporting constructs from later versions of standard C. This is true with or without -pedantic
You can not depend upon on gcc -std=c89 -pedantic to give you errors or warnings if you try to compile using some C99 code constructs. In some cases it will, in others it will not. For example, it will happily compile code that uses the %zu format specifier in a printf() call, even though it wasn't added until C99.
I found a way to query C++ version and adapted it for C:
gcc -dM -E -x c /dev/null | grep -F __STDC_VERSION__
Default gcc command is the GNU dialect of ISO C90 (including some C99 features). This is the default for C code.
I have the following C code:
#include <math.h>
int main(int argc, char ** argv)
{
double mydouble = 100.0;
double whatever = round(mydouble);
return (int) whatever;
}
When I compile this, I get the warnings:
round_test.c: In function ‘main’:
round_test.c:6: warning: implicit declaration of function ‘round’
round_test.c:6: warning: incompatible implicit declaration of built-in function ‘round’
I'm rusty with C, but I thought that the #include brought a declaration for round() into scope. I've checked my ANSI standard (C99 is the only copy I have) which confirms that the round() function exists in the math.h header. What am I missing here?
Edit: The compiler is GCC 4.3.2 on Ubuntu (intrepid, IIRC). Running gcc -E gives:
$ gcc -E round_test.c | grep round
# 1 "round_test.c"
# 1 "round_test.c"
# 2 "round_test.c" 2
double whatever = round(mydouble);
so the definition obviously isn't being found in the headers.
I see you're using gcc.
By default, gcc uses a standard similar to C89. You may want to "force" it to use the C99 standard (the parts it complies with)
gcc -std=c99 -pedantic ...
Quote from GCC Manual
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. Use of the -std
options listed above will disable
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=gnu89 (for C89 with GNU
extensions) or -std=gnu99 (for C99
with GNU extensions). The default, if
no C language dialect options are
given, is -std=gnu89; this will change
to -std=gnu99 in some future release
when the C99 support is complete. Some
features that are part of the C99
standard are accepted as extensions in
C89 mode.
Something must be wrong with your gcc installation, system headers, or compilation options.
Try compiling with -E. That will show you what the preprocessor output -- including which headers are being included and what's in them. On my Ubuntu Linux system it's about 1000 lines of output, including this:
extern double round (double __x) __attribute__ ((__nothrow__)) __attribute__ ((__const__));
You need to tell gcc that you want C99, and that you want to link in libm:
gcc -std=c99 -lm round_test.c
The code you type compiles cleanly on MacOS X 10.5.8 with GCC 4.0.1. If prodded with options '-Wall -Wextra', it complains about unused parameters argc and argv - not material.
Have you looked in <math.h> on your machine?
Have you tried with options such as '-stc=c99'?
C99 was the answer, but the full story is a little more complicated. The reason I'd been playing with this at all was that I was trying to compile a library written for Windows, which had its own "optimised" definition of round(). I got a linker error telling me that the definition conflicted with the built-in, so I removed the definition (and declaration). Once I'd done that I started to get the "implicit declaration error".
It seems that the default compile mode (without the -std=c99 flag) is neither conforming C89 nor C99: if it were conforming C89, you should be able to provide a custom definition of round() without conflicting, and if it were conforming C99 the declaration should be in math.h.
you need to link with the math library. So when you compile, be sure to add the -lm flag.