Does ANSI-C not know the inline keyword? - c

When compiling something as simple as
inline int test() { return 3; }
int main()
{
test();
return 0;
}
with gcc -c test.c, everything goes fine. If the -ansi keyword added, gcc -ansi -c test.c, one gets the error message
test.c:1:8: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘int’
This is true even if the C99 standard is explicitly selected, gcc -std=c99 -ansi -c test.c.
What is the reason for this, and is there a recommended fix?

You need to use:
gcc -std=c99 -c test.c
The -ansi flag specifies c90:
The -ansi option is equivalent to -std=c90.
ANSI C was effectively the 1990 version of C, which didn't include the inline keyword.

Nope, ANSI C doesn't have inline.
Your second command actually overrides -std=c99 with -ansi (they both affect -std=), so you are in effect compiling using ANSI C (no C99).

The inline keyword is not part of the original ANSI C standard
(C89) so the library does not export any inline function definitions
by default. Inline functions were introduced officially in the newer
C99 standard but most C89 compilers have also included inline as an
extension for a long time.
quoted from Gnu website

The reason it works fine without the ansi option at all is because gcc defaults to '-std=gnu90', which is ANSI/C89 plus extensions (one of which, not surprisingly, is support for inline functions). If you just want ANSI C support you don't need any options, unless you want strict standard compliance (which obviously may be useful if your code is going to be compiled on other compilers).

Related

How to disable GNU C extensions?

As you can see in the following code, I've introduced a nested function within main():
#include <stdio.h>
int main(){
int a=5;
printf("%d\n",a);
{
int a=10;
printf("%d\n",a);
}
printf("%d\n",a);
//Nested function
int main(int a){
if(a>0)printf("%d\n",a--);
return 0;
}
main(7);
return 0;
}
As far as I could understand I used the -std=c99 flag in gcc to "disable" the unnecessary extensions, but I did not get any error.
gcc temp3.c -std=c99 -o temp3.out
Where have I made the mistake?
Add -pedantic and -Werror to the command line.
Using GCC 6.1.0 on Mac OS X 10.11.6, with your original code in a file ped73.c and my default compilation options, I get:
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes \
> -Wold-style-definition ped73.c -o ped73
ped73.c:3:5: error: function declaration isn’t a prototype [-Werror=strict-prototypes]
int main(){
^~~~
ped73.c: In function ‘main’:
ped73.c:3:5: error: old-style function definition [-Werror=old-style-definition]
ped73.c:13:6: error: ‘main’ takes only zero or two arguments [-Werror=main]
int main(int a){
^~~~
ped73.c:13:6: error: ‘main’ is normally a non-static function [-Werror=main]
$
Renaming the nested function to nested and using int main(void), I get:
$ gcc -O3 -g-std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes
> -Wold-style-definition -o ped73
$
Using the extra option -pedantic I get:
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes \
> -Wold-style-definition -pedantic ped73.c -o ped73
ped73.c: In function ‘main’:
ped73.c:13:2: error: ISO C forbids nested functions [-Werror=pedantic]
int nested(int a){
^~~
cc1: all warnings being treated as errors
$
Then what's the point of -std=c99?
The -std=c99 flag disables the GNU extensions that GCC thinks should be disabled — such as POSIX versions, etc. See C Dialect Options for the meaning of -std=; see Warning Options for the meaning of -pedantic.
-Wpedantic
-pedantic
Issue all the warnings demanded by strict ISO C and ISO C++; reject all programs that use forbidden extensions, and some other programs that do not follow ISO C and ISO C++. For ISO C, follows the version of the ISO C standard specified by any -std option used.
Valid ISO C and ISO C++ programs should compile properly with or without this option (though a rare few require -ansi or a -std option specifying the required version of ISO C). However, without this option, certain GNU extensions and traditional C and C++ features are supported as well. With this option, they are rejected.
-Wpedantic does not cause warning messages for use of the alternate keywords whose names begin and end with __. Pedantic warnings are also disabled in the expression that follows __extension__. However, only system header files should use these escape routes; application programs should avoid them. See Alternate Keywords.
Some users try to use -Wpedantic to check programs for strict ISO C conformance. They soon find that it does not do quite what they want: it finds some non-ISO practices, but not all—only those for which ISO C requires a diagnostic, and some others for which diagnostics have been added.
A feature to report any failure to conform to ISO C might be useful in some instances, but would require considerable additional work and would be quite different from -Wpedantic. We don't have plans to support such a feature in the near future.
Where the standard specified with -std represents a GNU extended dialect of C, such as ‘gnu90’ or ‘gnu99’, there is a corresponding base standard, the version of ISO C on which the GNU extended dialect is based. Warnings from -Wpedantic are given where they are required by the base standard. (It does not make sense for such warnings to be given only for features not in the specified GNU C dialect, since by definition the GNU dialects of C include all features the compiler supports with the given option, and there would be nothing to warn about.)
And there's also a different option that gives pedantic errors:
-pedantic-errors
Give an error whenever the base standard (see -Wpedantic) requires a diagnostic, in some cases where there is undefined behavior at compile-time and in some other cases that do not prevent compilation of programs that are valid according to the standard. This is not equivalent to -Werror=pedantic, since there are errors enabled by this option and not enabled by the latter and vice versa.
There are multiple questions about which GCC compiler options to use, including:
Recommended gcc warning options for C
What is the purpos of using -pedantic in GCC/G++ compiler
warning: implicit declaration of function when compiling C source
and no doubt there are many others that could be added to that list. Basically, the default options I use ensure that functions are declared before they are used (or, are defined as a static function before they are used), and that the function declarations have full prototypes — no empty parentheses () — and use the -Wall and -Wextra to spot a number of other routine problems, including mismatches between format strings and arguments to the printf() and scanf() families of functions.

Forcing compiler to C99 standard

I was coding on my project when I discovered that the anonymous structs I've been using for a while are actually only available in C11, not C99, the standard I want to code against.
Given the following code:
struct data {
int a;
struct {
int b;
int c;
};
};
int main()
{
struct data d;
d.a = 0;
d.b = 1;
d.c = 2;
return 0;
}
This code should only compile in C11 (or if compiler extensions provide this feature and are enabled). So let's see the results on different compilers:
clang 5
compiler:
Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin13.1.0
Thread model: posix
command:
clang -std=c99 -Wall test.c -o test
result:
**OK**
gcc 4.1
compiler:
gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-54)
command:
gcc -std=c99 -Wall test.c -o test
result:
**NOT OK**
test.c:6: warning: declaration does not declare anything
test.c: In function 'main':
test.c:14: error: 'struct data' has no member named 'b'
test.c:15: error: 'struct data' has no member named 'c'
gcc 4.7
compiler:
gcc (GCC) 4.7.2 20121109 (Red Hat 4.7.2-8)
command:
gcc -std=c99 -Wall test.c -o test
result:
**OK**
test.c: In function 'main':
test.c:11:14: warning: variable 'd' set but not used [-Wunused-but-set-variable]
I've always tried to force the compiler to C99 mode by specifying -std=c99, but obviously this doesn't work (except for gcc 4.1 which compiles fine without the -std parameter).
So my question is now, how can I force the compilers gcc and clang, in any version, to issue an error if I write code that does not conform to the standard I specify using -std? Is there some command line argument that I don't know of?
-std=c99 won't disable language extensions (GNU C has anon structs in C99).
The -pedantic (or -pedantic-errors) flags make the compiler warn on language extensions.
Both gcc and clang allow a large number of extension and here for clang. clang in general attempts to support most of the extensions that gcc does. Both will even allow you to use features that are C only in C++ for example VLAs which are a C99 feature.
In this case both are allowing you to use Unnamed struct/union fields within structs/unions in C99 mode even though it is a C11 feature.
The Language Standards Supported by GCC documents well what flags are required to turn these into warnings and errors and as far as I know clang follows the same conventions:
[...]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). [...]
So -pedantic will warn you if you are using an extension and -pedantic-errors will turn these warnings into an error. With -pedantic flag you should see a warning like this in gcc:
warning: ISO C99 doesn't support unnamed structs/unions [-Wpedantic]
and this in clang (see it live):
warning: anonymous structs are a C11 extension [-Wc11-extensions]
and it turn into an error with -pedantic-errors.

gcc - pedantic wont compile, ISO C90 forbids mixed declarations and code How to fix this?

I need that code for my program to have colors. But it wont compile if i use -pedantic. Is there a way around this? its btw
gcc -pedantic MP1.c -o hahah
MP1.c: In function `main':
MP1.c:65: warning: ISO C90 forbids mixed declarations and code
MP1.c:686:30: warning: (this will be reported only once per input file)
line 65:
int originalAttrs = ConsoleInfo.wAttributes;
Move declaration of originalAttrs to the top of the scope in which it is used. The error is unrelated to use of ConsoleInfo.wAttributes but to the location of the declaration of originalAttrs. Without seeing the entire code, it is probably something like:
printf("hello\n"); /* For example. */
int originalAttrs = ConsoleInfo.wAttributes;
To fix:
int originalAttrs;
printf("hello\n"); /* For example. */
originalAttrs = ConsoleInfo.wAttributes;
Either fix the code so it complies with the C90 standard (as hmjd's answer suggests), or tell gcc to use a newer version of the standard.
C does permit mixed declarations and statements starting with the C99 standard.
If you use
gcc -std=c99 -pedantic
or
gcc -std=c11 -pedantic
it should work.

Are "Statement and Declarations in Expressions" specific to GNU C?

Are Statement and Declarations in Expressions specific to GNU C ? Or this feature is also included in C99 standard ?
It's a GCC extension. (See the GCC docs, e.g. here for gcc 4.3.3, for a full list of GCC extensions; and the C99 spec is available here.)
GCC will warn about such things if you use the -pedantic -std=c99 flags, e.g.:
$ cat foo.c
int main(void)
{
return ({ int a = 0; a; });
}
$ gcc -pedantic -std=c99 -c foo.c
foo.c: In function 'main':
foo.c:3: warning: ISO C forbids braced-groups within expressions
While this is not a C99 standard, this extension is not specific to gcc either.
For instance, the clang compiler and Intel C++ compiler support this extension.
It's a GNU C extension. That's what they mean by "may appear ... in GNU C." (my emphasis)

Why does gcc report "implicit declaration of function ‘round’"?

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.

Resources