繁体   English   中英

即使包含头文件,ntohll也会收到“函数的隐式声明”错误

[英]ntohll gets “implicit declaration of function” error even if header files are included

我已经包含了这些头文件,即使如此,我仍收到此错误

#include <sys/types.h>
#include <netinet/in.h>
#include <inttypes.h>


error: implicit declaration of function ‘ntohll’ [-Werror=implicit-function-declaration]
            uint64_t bits = ntohll(*(uint64_t *)tmp);

ntohll不是AFAICT的标准功能。 它存在于现代Solaris UNIX(如您的评论中的链接所述)上,并且Windows提供了它 (来自WinSock2.h标头),但是它不是任何通用标准(例如POSIX)的一部分,并且在很多(大多数/全部)中都找不到?)“类UNIX”系统,例如Linux和BSD。

许多缺少它的系统的确为be64toh提供了相同的含义(尽管它来自的标头并不一致,甚至在BSD社区中也有所不同)。 他们只是说“ be”明确表示big-endian,用64明确表示位大小,而“ network”则用“ n”表示所有网络协议都是big endian(Windows协议通常不是,而不是ll ),这是一种不太清楚的方式来说明它适用于64位值。

如果您需要可移植的代码,则需要进行一系列OS检测以确定要包含的标头,并根据您的OS实际提供的功能使用宏(或内联函数等)为功能提供通用名称。

您的代码段隐式声明了ntohll函数的另一个原型,这正是gcc抱怨的。

您的代码使用:

ntohll(*(uint64_t *)tmp)

但是,头文件中的原型为:

uint64_t htonll(uint64_t hostlonglong);

注意缺少** ,更不用说*(uint64_t *)

如果您从函数调用中删除了强制类型转换(假设您对变量tmp并没有做任何疯狂的事情),那么我希望它能起作用。

系统可能不支持htonll,ntohll。 通过宏实现功能。 您需要检查字节顺序宏。 如果您不知道此系统的字节顺序,请使用下面的is_big_endian()函数。

我测试了这段代码。

#include <stdio.h>

#include <sys/types.h>
#include <netinet/in.h>
#include <inttypes.h>

#if __BIG_ENDIAN__
    #define htonll(x)   (x)
    #define ntohll(x)   (x)
#else
    #define htonll(x)   ((((uint64_t)htonl(x&0xFFFFFFFF)) << 32) + htonl(x >> 32))
    #define ntohll(x)   ((((uint64_t)ntohl(x&0xFFFFFFFF)) << 32) + ntohl(x >> 32))
#endif

void dump_bin(unsigned char *p, int len) {
    int i=0; 
    for (i=0; i<len; i++) {
        printf("%02x ", p[i]) ;
    }
    printf("\n");
}

int is_big_endian() {
    union {
        int i ;
        char c[4] ;
    } v = { 0x00000001 } ;
    return v.c[3]==1 ;
}

int main() {

    #if __BIG_ENDIAN__
        printf("macro: big_endian.\n") ;
    #else
        printf("macro: little_endian.\n") ;
    #endif

    printf("System is big endian? : %d\n", is_big_endian());

    long long ll=123456789012345678L;
    long long ll2=0;

    printf("long long value=%lld\n", ll) ;
    dump_bin((unsigned char*)&ll, sizeof(ll)) ;

    ll2=htonll(ll) ;
    printf("htonll=%lld\n", ll2) ;
    dump_bin((unsigned char*)&ll2, sizeof(ll2)) ;

    return 0 ;
}

输出在这里。

macro: little_endian.
System is big endian? : 0
long long value=123456789012345678
4e f3 30 a6 4b 9b b6 01 
htonll=5688944245090268673
01 b6 9b 4b a6 30 f3 4e 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM