3

当我编译以下程序时(我从C++ 中的 64 位 ntohl() 获得的所有定义的代码?这似乎很明智):

#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;
}

使用以下命令编译时出现链接错误(我正在运行 linux):

gcc -std=c99 endian_test.c -o endian

我收到的错误是:

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

对我来说,这表明了两件事,标头本身已包含在内,但并不真正包含此工作所需的函数/宏,因为这意味着编译器希望它稍后会找到该函数,它无论如何都会尝试继续但在尝试时失败链接。

但是,如果我使用以下命令进行编译(只需删除-std=c99):

gcc endian_test.c -o endian

一切都像黄油一样光滑并且有效。知道为什么会发生这种情况以及我能做些什么来补救吗?对我来说,内核给出的函数(或者我在这个事实上错了吗?)根据我在编译时使用的标准而改变是没有意义的?

提前致谢!

4

4 回答 4

4

如果没有显式-std=选项,调用gcc-std=gnu89使用 C89 + GNU 扩展相同。GNU 扩展将启用宏,这将使您的标头中存在功能。

于 2013-10-22T18:19:38.393 回答
3

如果您查看be64toh手册,您将看到它需要_BSD_SOURCE定义。所以在 Linux 上#define它之前包含<endian.h>.

于 2013-10-22T18:20:48.607 回答
1

我有这个问题。解决方案是不仅要声明

#define _BSD_SOURCE 

但是也

#define __USE_BSD

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

于 2015-06-09T12:50:55.950 回答
1

最近对 glibc 的更改意味着您需要

#define _DEFAULT_SOURCE

代替

#define _BSD_SOURCE

_BSD_SOURCE 和 _SVID_SOURCE 功能宏的弃用

于 2015-08-12T07:08:51.650 回答