3

When I compile the following program (the code for all the defines I've gotten from 64 bit ntohl() in C++? which seemed sensible):

#include <stdint.h>
#if defined(__linux__)
#include <endian.h> //htobe64,be64toh
#include <arpa/inet.h> //ntohs, ntohl, htonl, htons
#elif defined(__FreeBSD__) || defined(__NetBSD__)
#include <sys/endian.h>
#elif defined(__OpenBSD__)
#include <sys/types.h>
#define be16toh(x) betoh16(x)
#define be32toh(x) betoh32(x)
#define be64toh(x) betoh64(x)
#endif

int main()
{
    int64_t i = 0x1212121234343434;
    int64_t j = be64toh(i);
    return 0;
}

I get a linking error when compiling it with the following command (I'm running linux):

gcc -std=c99 endian_test.c -o endian

The error i receive is:

user@host ~/src/c $ gcc -std=c99 derp.c 
endian_test.c: In function ‘main’:
endian_test.c:17:2: warning: implicit declaration of function ‘be64toh’ [-Wimplicit-function-declaration]
  int64_t j = be64toh(i);
  ^
/tmp/ccYonfH4.o: In function `main':
endian_test.c:(.text+0x23): undefined reference to `be64toh'
collect2: error: ld returned 1 exit status

Which to me indicates two things, the header itself is included but doesn't really contain the functions/macros needed for this to work and because that means the compiler hopes it's gonna find the function later it tries to go ahead anyway but fails when trying to link.

But if i use the following command to compile (just remove -std=c99):

gcc endian_test.c -o endian

Everything is smooth as butter and works. Any idea why it's happening and what i could do to remedy it? To me it doesn't make sense that functions given by the kernel (or am i mistaken in that fact?) change depending on what standard i use when compiling?

Thanks in advance!

Community
  • 1
  • 1
lfxgroove
  • 3,778
  • 2
  • 23
  • 33

4 Answers4

5

Without explicit -std= option, calling gcc is the same as -std=gnu89 with means C89 + GNU extensions. The GNU extensions will enable macros which will enable the presence of the functions in your header.

ouah
  • 142,963
  • 15
  • 272
  • 331
  • Does the same apply to `-std=gnu99`? And is that a feasible workaround? – lfxgroove Oct 22 '13 at 18:22
  • Yes, it does apply to `-std=gnu99`. Both options define `__USE_BSD` macros used in `endian.h`. A workaround to your issue is to to just `#define __USE_BSD` before including `endian.h`. – ouah Oct 22 '13 at 18:33
  • That's not really portable either is it? x) I'll just keep to using gnu99 as the standard for now then. Thanks! – lfxgroove Oct 22 '13 at 18:46
3

If you see the be64toh manual, you will see that it needs the _BSD_SOURCE to be defined. So on Linux #define it before you include <endian.h>.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
1

I had this problem. The solution was to declare not only

#define _BSD_SOURCE 

but also

#define __USE_BSD

https://github.com/tailhook/zerogw/pull/34/files#r32008569

h4ck3rm1k3
  • 2,060
  • 22
  • 33
1

Recent changes to glibc has meant you need

#define _DEFAULT_SOURCE

instead of

#define _BSD_SOURCE

Deprecation of _BSD_SOURCE and _SVID_SOURCE feature macros

johndrinkwater
  • 253
  • 2
  • 6