Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does C99 complain about storage sizes?

This is some code I'm compiling on Linux:

#include <net/if.h>

int main() {
  struct ifreq ifr;
}

gcc test.c is fine.

gcc -std=gnu99 test.c is fine.

gcc -std=c99 test.c fails with the following error:

test.c: In function ‘main’:
test.c:4:16: error: storage size of ‘ifr’ isn’t known

What's different about C99 that it doesn't like the definition of struct ifreq in Linux?

like image 288
Jim Hunziker Avatar asked May 03 '12 14:05

Jim Hunziker


1 Answers

It's a chain of consequences of preprocessing and GNU C vs C99.

First up, net/if.h:

  1. net/if.h includes features.h
  2. Later on, it defines struct ifreq inside a #ifdef __USE_MISC block.

So:

  1. What is __USE_MISC? -- it is stuff common to BSD and System V
  2. Is it defined at this point? -- We need to check that out in features.h

So now, features.h:

  1. When you use --std=c99 GCC by default defines __STRICT_ANSI__ (since thats what C99 is)
  2. While preprocessing features.h, when __STRICT_ANSI__ is on, the BSD and System V features don't kick in. i.e. __USE_MISC is left undefined.

Back up to net/if.h: struct ifreq does not even exist after preprocessing! Therefore, the complaint about storage size.

You can catch the whole story by doing:

vimdiff <(cpp test.c --std=c99 -dD) <(cpp test.c --std=gnu99 -dD)

or diff'ing them in any other way (like diff --side-by-side) instead of vimdiff.

If you want this to cleanly compile with -std=c99, you must consider the inclusion of the _DEFAULT_SOURCE feature test macro (for glibc versions >= 2.19; for older glibc versions, use either _BSD_SOURCE or _SVID_SOURCE) so that the required functionality is enabled on top of what is offered by C99.

like image 133
ArjunShankar Avatar answered Oct 08 '22 02:10

ArjunShankar