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

时间:2018-03-07 23:53:44

标签: c

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

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

3 个答案:

答案 0 :(得分:0)

ntohll不是AFAICT的标准功能。它存在于现代Solaris UNIX上(作为注释中的链接提及)和Windows provides it(来自WinSock2.h头文件),但它不是任何通用标准(例如POSIX)的一部分,并且未找到在许多(大多数/全部?)&#34;类UNIX&#34;系统,例如Linux和BSD。

缺少它的许多系统确实提供be64toh而不是相同的含义(尽管它来自的标题不是一致的,即使在BSD社区内也是如此);他们只是说&#34; be&#34;明确表示big-endian,64表示明确比特大小,而不是&#34; n&#34; for&#34; network&#34;假设所有网络协议都是大端(Windows协议通常不是,其他人不确定),而ll这是一种不太明确的方式,表明它适用于64位值。

如果您需要可移植代码you'll need to do a bunch of OS detection来确定要包含哪些标头,并使用宏(或内联函数等)根据您的操作系统实际提供的内容提供功能的通用名称。

答案 1 :(得分:0)

您的代码段隐式声明了ntohll函数的不同原型,这正是gcc所抱怨的。

您的代码使用:

ntohll(*(uint64_t *)tmp)

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

uint64_t htonll(uint64_t hostlonglong);

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

如果从调用函数中删除强制转换(假设你对变量tmp没有做任何疯狂的事情)那么我希望它可以工作。

答案 2 :(得分:0)

系统可能不支持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