warning: implicit declaration of function 'fsync' is invalid in C99 - c

For some reason when I compile my code the compiler does not find the prototypes for fsync and truncate. I get this:
cc -c -Wall -Wno-overflow -pedantic -std=c99 -I/Users/matt/Programming/BitEagle_Projects/cbitcoin/include -I/usr/local/ssl/include -I/opt/local/include -O3 -arch i386 -arch x86_64 -D_POSIX_SOURCE -fPIC dependencies/storage/CBBlockChainStorage.c -o build/CBBlockChainStorage.o
dependencies/storage/CBBlockChainStorage.c:154:6: warning: implicit declaration of function 'fsync'
is invalid in C99 [-Wimplicit-function-declaration]
if(fsync(indexAppend)){
^
dependencies/storage/CBBlockChainStorage.c:649:6: warning: implicit declaration of function
'truncate' is invalid in C99 [-Wimplicit-function-declaration]
if (truncate(filename, CBArrayToInt32(data, 0))) {
^
What do I have to do to remove these warnings? I am including unistd.h. This is on OSX using clang:
$ cc --version
Apple clang version 4.0 (tags/Apple/clang-421.0.60) (based on LLVM 3.1svn)
Target: x86_64-apple-darwin12.2.0
Thread model: posix
Thank you.

If you are using -std=c99, the system headers will attempt to provide a declaration/macro namespace compatible with the C standard, which does not include any of the additional functions from POSIX or other standard or nonstandard extensions. You need to define the appropriate feature test macros to get them. For example, put -D_POSIX_C_SOURCE=200809L on the command line or define it in your source files.

Related

undefined reference to `le16toh' error in Makefile

I'm trying to compile a C program with the following Makefile:
msh: libFAT32.so
gcc -Wall -fPIC -I. -o msh newTest.c -L. -lFAT32
libFAT32.so:
gcc -std=c99 -shared -o libFAT32.so -fPIC fat32.c
clean:
rm *.so msh
However, every time I try to compile the program with make I get the following error:
user#user-VirtualBox:~/fat1$ make
gcc -Wall -fPIC -I. -o msh newTest.c -L. -lFAT32
./libFAT32.so: undefined reference to `le32toh'
./libFAT32.so: undefined reference to `le16toh'
collect2: error: ld returned 1 exit status
Makefile:19: recipe for target 'msh' failed
make: *** [msh] Error 1
Can some one tell how to fix this?
So, here's what's going on (making the safe assumption that you're using a linux distribution in your VM).
With this test program:
#include <stdio.h>
#include <endian.h>
int main(void) {
printf("%d\n", le32toh(1234));
return 0;
}
compiling and running it works:
$ gcc -Wall -Wextra test.c
$ ./a.out
1234
However, you're compiling using -std=c99. So let's try that:
$ gcc -std=c99 -Wall -Wextra test.c
test.c: In function ‘main’:
test.c:5:18: warning: implicit declaration of function ‘le32toh’ [-Wimplicit-function-declaration]
printf("%d\n", le32toh(1234));
^~~~~~~
/tmp/cc7p3cO8.o: In function `main':
test.c:(.text+0xf): undefined reference to `le32toh'
collect2: error: ld returned 1 exit status
Compiling in c99 mode disables a bunch of functions and macros and such that aren't in the 1999 version of the C standard unless they're explicitly requested, hence the implicit declaration warning. le32toh() is a macro, not a function with a symbol in libc, hence the linker error.
If you read the man page for le32toh(), you'll see that it needs the _DEFAULT_SOURCE feature test macro, which must be defined before any headers are included.
So, your options are:
Compile in gnu99 mode instead, since that automatically defines a bunch of the feature test macros.
Continue to use c99 mode and add a #define _DEFAULT_SOURCE at the very start of your fat32.c source file.
Continue to use c99 mode and add -D_DEFAULT_SOURCE to your compiler arguments.

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.

Linking non C99 static library in C99 mode

I have a static library which I compiled with gcc without c99 mode. I am trying to link it in compilation using gcc -std=c99. This is giving me an error:
undefined reference to 'functionName'
Here, functionName is function inside the static library.
This is my compilation:
gcc -std=c99 -g -I../ -Llib/ -lmylib test.c ../file1.c ../file2.c -o test
I am using C99 here because my code in test.c #includes header files whose implementation uses C99 standard.
The static library(lib/libmylib.a) in not compiled with c99 standard because it's code uses some libraries which are failing to compile in C99 mode(but compiles without c99 flag).
I also tried changing the order of the -L & -l flags to the end & immediately after gcc -std=c99 but it gave the same 'undefined reference' error.
How do I link these together?
Thank you.
EDIT: The function which I've mentioned as functionName is a pseudonym for setupStacktrace() shown here: http://pastebin.com/2RbEEPaj. It is signature is void setupStacktrace();
The order of the command line arguments matter. The way you have it now, the linker goes through your static libraries, realizes that nothing so far need anything it provides, and throw away everything in it. Do this:
gcc -std=c99 -g -I../ -Llib/ test.c ../file1.c ../file2.c -lmylib -o test

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)

Resources