1

I have included these header files, even then too, I am getting this error

#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);
sephora
  • 21
  • 1
  • 7

3 Answers3

1

The system may not support htonll, ntohll. Implement the functions by macro. You need to check the byte order macro. If you don't know this system's byte ordering, use is_big_endian() function below.

I tested this code.

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

The output is here.

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 
Junhee Shin
  • 748
  • 6
  • 8
0

ntohll is not a standard function AFAICT. It exists on modern Solaris UNIX (as your link in the comments mentions), and Windows provides it (from the WinSock2.h header), but it's not part of any common standard (e.g. POSIX) and not found on many (most/all?) "UNIX-like" systems, e.g Linux and the BSDs.

Many of the systems that lack it do provide be64toh instead with identical meaning (though the headers it comes from aren't consistent, varying even within the BSD community); they're just saying "be" to mean big-endian explicitly and 64 to make the bit size explicit, as opposed to "n" for "network" which assumes all network protocols are big endian (Windows protocols often aren't, not sure on others), and ll which is a less clear way of spelling out that it works on 64 bit values.

If you need portable code, you'll need to do a bunch of OS detection to determine which headers to include, and use macros (or inline functions or the like) to provide a common name for the functionality based on whatever your OS actually provides.

ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
0

Your code snippet implicitly declares a different prototype for the ntohll function, which is what gcc is complaining about.

Your code uses:

ntohll(*(uint64_t *)tmp)

However, the prototype in the header file is:

uint64_t htonll(uint64_t hostlonglong);

Note the lack of **, let alone *(uint64_t *).

If you remove the cast from your invocation of the function (assuming you're not doing anything crazy with the variable tmp) then I'd expect it to work.

James McPherson
  • 2,476
  • 1
  • 12
  • 16