16

I am trying to compile a C program on a Linux system. I have an #include statement for stdlib.h.

When I compile the program with gcc as follows:

gcc -std=c99 -g -o progfoo progfoo.c progbar.c

I get warnings about Implicit declaration of function [srand48, drand48, bzero, or close].

Compiling instead as:

gcc -g -o progfoo progfoo.c progbar.c

doesn't give me the warnings, but it does yell about my use of for loops (which was the rationale for adding -std=c99 in the first place).

Given that man srand48 mentions including <stdlib.h>, which I have, I'm unsure what else the problem could be. The for loops aren't essential to anything (they were just to save time in initializing an array) so I have no problem removing them, but before I do I'd like to confirm whether the c99 standard is superseding some aspect of my #include statements.

I'm using gcc 4.1.2-50 (Red Hat).

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
Raven Dreamer
  • 6,940
  • 13
  • 64
  • 101

6 Answers6

12

Can -std=c99 prevent my #includes from working properly?

No, but they may show up limitations in your knowledge of how they work :-)


While the functions [sd]rand48 have a prototype in stdlib.h, they're inside an #ifdef, at least on my system:

#if defined __USE_SVID || defined __USE_XOPEN

So you will probably have to explicitly set one of those macros.

However, before you try it, be aware that it doesn't work. That's because all this stuff is controlled with gcc's feature test macros.

There's a very complicated set of rules used to set specific features on or off in features.h and the macros created there control what the header files include and exclude. The __USE_* variants are cleared and set in that header file based on other macros provided by yourself.

For example, to get __USE_SVID set so you can use srand48, you need to provide the compiler with a -D_SVID_SOURCE parameter.

But perhaps an easier way is to just use C99 with the GNU extensions. To do that, replace -std=c99 with -std=gnu99.

And, for bzero and close, these can be obtained from strings.h and unistd.h respectively.

I was a little confused at first as to why these compiled with -std=c99 when they have absolutely nothing to do with C99 but then I realised that flag only controls what the standard C headers give you.

Neither strings.h (note the plural name, this is not string.h) nor unistd.h are part of ISO C.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • Good point, @Matteo, I tend to think of _macros_ as the ones that _do_ things, like `#define halfOf(x) ((x) / 2)`, as opposed to just "flags" to control compilation. But you're correct and the use of the work "variable" by myself is apt to lead to confusion with real variables. So I changed it as per your suggestion. – paxdiablo Feb 04 '11 at 01:28
  • 2
    Right. It might be helpful to know that when you compile with no `-std=` flag, you are asking for `-std=gnu89`, which is C89 plus GNU extensions - so the C99 equivalent to this mode is `-std=gnu99`. – caf Feb 04 '11 at 01:53
  • 1
    It is better to learn how to enable POSIX extensions in the standard way, because messing with `__USE_SVID` or `__USE_XOPEN` are inherently unportable. They work on some machines (probably Linux-ish), but won't work on other machines. Using `-D_XOPEN_SOURCE=600` or `-D_POSIX_C_SOURCE=200809L` is better - hence [Kevin](http://stackoverflow.com/users/458988/kevin)'s answer is the better solution. – Jonathan Leffler Feb 04 '11 at 17:37
  • Normally, I'd agree but, since the tags specifically stated Linux and the question stated RedHat, I assumed portability wasn't of great importance. – paxdiablo Feb 05 '11 at 14:02
6

Looks like the functions that you are using are not ISO C99, so when you request strict C99 compliance they will not be visible.

Information here: https://bugzilla.redhat.com/show_bug.cgi?id=130815

The flag -D_POSIX_C_SOURCE=200809L should work.

See also this question: Why can't gcc find the random() interface when -std=c99 is set?

Community
  • 1
  • 1
Kevin
  • 1,889
  • 14
  • 11
  • 2
    Just like I have to make a function prototype for "printf" in HelloWorld.c? I don't think you quite understand my problem. – Raven Dreamer Feb 04 '11 at 00:43
  • He is getting a warning about the system include files(stdlib.h) if I understand right, not in his own code. – Earlz Feb 04 '11 at 00:48
  • Sorry, didn't realize those functions were not self-written because I only write C99 code and have never used them. Edited my answer. – Kevin Feb 04 '11 at 00:58
  • `-D_POSIX_C_SOURCE=200809L` is the correct portable way to do this. `-D_GNU_SOURCE` is glibc-specific. – R.. GitHub STOP HELPING ICE Feb 04 '11 at 01:11
  • My only beef with this answer is that I believe the definition should go in the source file itself (the very first thing in any source file), not on the command line. After all, it is the source code itself that requires the features enabled by the POSIX feature test macros, not the build environment. Otherwise, good answer. – Dan Moulding Mar 12 '12 at 15:44
3

The error you're getting makes it sound like the functions you're using aren't being declared. Are you sure you're including the correct headers for them?

Also, using -std=c99 may disable some extensions which are not part of the standard. None of the functions you mentioned are part of the C standard. If you can't find separate headers for them, you might try -std=gnu99.

Jay Conrod
  • 28,943
  • 19
  • 98
  • 110
2

-std=c99 causes the headers to omit anything that could clash with uses of names outside the C99 reserved namespace, including all standard POSIX functions. The portable way to request the headers give you the POSIX interfaces is to define _POSIX_C_SOURCE to a value corresponding to the desired POSIX version. For the latest POSIX (2008), this means:

#define _POSIX_C_SOURCE 200809L

or on the command line:

-D_POSIX_C_SOURCE=200809L

Edit: It seems the functions you want are not in the POSIX base but in the XSI option, so you should define _XOPEN_SOURCE to an appropriate value (700 is the latest) to get them. This too can be done from the command line or your source files (but if from the source files, it must be done before including any system headers.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
1

Implicit declarations (where an undeclared function is assumed to return int) are no longer allowed in C99.

That said, gcc will not abort the compilation.

Try to include strings.h for bzero, see also paxdiablo's answer.

Artefacto
  • 96,375
  • 17
  • 202
  • 225
  • I think this is what happening: nothing's actually *different*, but the implicit function definitions just aren't being reported without c99's standards. Which means my #includes simply aren't working for whatever reason. Hell... – Raven Dreamer Feb 04 '11 at 00:56
1

You're asking for standards compliance, and C99 doesn't define srand48() as a function provided by <stdlib.h>.

For the GNU C library, you can request additional features by defining one or more of the options listed in the comment at the top of /usr/include/features.h, either by #define before you #include, or with -D flag to gcc.

For srand48() (and drand48()) you probably want either -D_XOPEN_SOURCE=500 or -D_SVID_SOURCE (or #define _XOPEN_SOURCE 500 etc. in the source files).

bzero() and close() should work even with -std=c99 if you #include the documented header files for them, which are <strings.h> and <unistd.h> respectively.

Matthew Slattery
  • 45,290
  • 8
  • 103
  • 119