Intel® C++ Compiler
Community support and assistance for creating C++ code that runs on platforms based on Intel® processors.
7956 Discussions

compilation error with ntohs/htons function with icc under linux

zer0droids
Beginner
1,212 Views

The following code does not compile with icc under linux (tested with a debian-testing and a fedora core 10).

#include 
#include 
#include 
#include 

int main(void)
{
        uint16_t x = 0x1234;
        uint16_t y;

        y = ntohs(x);
        printf("ntohs(%x)=%x\\n", x, y);
        return 0;
}

With gcc it compiles without warning:

$ gcc -Wall -W toto.c

With icc:

$ icc -Wall -Werror-all -w2 toto.c
toto.c(11): error #2259: non-pointer conversion from "int" to "unsigned short" may lose significant bits
        y = ntohs(x);
            ^

compilation aborted for toto.c (code 2)

$ icc -V
Intel C Intel 64 Compiler Professional for applications running on Intel 64, Version 11.1    Build 20100203 Package ID: l_cproc_p_11.1.069
Copyright (C) 1985-2010 Intel Corporation.  All rights reserved.

I tried different kind of casts without success, and I suspect that this error may be a bug. Does someone has an idea about how to solve the issue without removing the "-Wall -Werror-all -w2" options ?

Thanks !

0 Kudos
6 Replies
Om_S_Intel
Employee
1,212 Views
You can compile it as below:

$ icpc -Wall tstcase.cpp

tstcase.cpp(11): remark #2259: non-pointer conversion from "int" to "unsigned short" may lose significant bits

y = ntohs(x);

You are not able to compile as you are forcing all warnings to error.

0 Kudos
zer0droids
Beginner
1,212 Views

Yes, but why is there a warning ? The prototype of the function is:

uint16_t ntohs(uint16_t netshort);

In my opinion there is no implicit cast in this case.

0 Kudos
mecej4
Honored Contributor III
1,212 Views
Is the prototype in one of the included files? On Suse 11.1, ntohs is defined in , not in
0 Kudos
zer0droids
Beginner
1,212 Views
Yes, I checked that includes .
I also checked that an undeclared prototype triggers an error.
0 Kudos
Judith_W_Intel
Employee
1,212 Views
After preprocessing the file (with -E) I see that the call has been turned into a Gnu statement expression, i.e.:

int main(void)
{
uint16_t x = 0x1234;
uint16_t y;

y = (__extension__ ({ register unsigned short int __v, __x = (x); if (__builtin_constant_p (__x)) __v = ((((__x) >> 8) & 0xff) | (((__x) & 0xff) << 8)); else __asm__ ("rorw $8, %w0" : "=r" (__v) : "0" (__x) : "cc"); __v; }));
printf("ntohs(%x)=%x\n", x, y);
return 0;
}

It looks like ntohs is a macro that is defined as __bswap_16 in netinet/in.h and __bswap_16 is a macro that is expanded in bits/byteswap.h to the expression above. If you turn off optimization (i.e. -O0)then this doesn't happen because __OPTIMIZE__ is not defined.

The remark looks valid to me since __v is an unsigned short and x is an uint16_t. I think this is sort of a bug/problem with the Gnu headers.

Judy

0 Kudos
zer0droids
Beginner
1,212 Views

Hi Judy,

Thank you for your answer. That helped me to find the root cause of the warning.

The code below is equivalent to the original code of my first message, with macros expanded. If I change the definition of __bswap_constant_16() and force the cast in unsigned short (or uint16_t, which is usually the same), there is no warning anymore. See the example below.

#include 

#ifndef FORCE_CAST
/* Swap bytes in 16 bit value.  */
#define __bswap_constant_16(x) \
      (((x) >> 8) & 0xff) | (((x) & 0xff) << 8))
#else
/* Swap bytes in 16 bit value.  */
#define __bswap_constant_16(x) \
      ((unsigned short int)((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)))
#endif

int main(void)
{
      unsigned short int x = 0x1234;
      unsigned short int y;

      y = (__extension__
           ({ register unsigned short int __v, __x = (x);
                   if (__builtin_constant_p (__x))
                           __v = __bswap_constant_16 (__x);  /* <<<<< cast warning here */
                   else
                           __asm__ ("rorw $8, %w0"
                                    : "=r" (__v)
                                    : "0" (__x)
                                    : "cc");
                   __v; }));

      printf("ntohs(%x)=%x\n", x, y);
      return 0;
}

Regards, Olivier

0 Kudos
Reply