CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 18
  1. #1
    Join Date
    Apr 2001
    Posts
    1,029

    endianness questions

    Hello,

    I am receiving data in Network Byte Order (big endian) and I am on an Intel machine so I am converting it to Little Endian.

    1. I get this error when trying to convert 32 bit values:

    Code:
    float position;
    memcpy(&position, &message[0], 4);  // message is of type vector<char>
    position=ntohl(position);
    warning C4244: 'argument' : conversion from 'float' to 'u_long', possible loss of data

    Am I doing something worng here?

    2. When I use structures I get an error:

    Code:
    struct data
    {
        unsigned short int temp: 16;
        unsigned short int flag : 1;  
        unsigned short int temp2: 15;
    } dat;
    
    bool flag_;
    
    memcpy(&dat, &message[4], 4);  
    dat=ntohl(dat);
    flag_=dat.flag;
    error C2664: 'ntohl' : cannot convert parameter 1 from CTest:ata' to 'u_long'



    How can I fix these issues?

    Thanks!

  2. #2
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,398

    Re: endianness questions

    1. It is NOT an "error", it is a "warning" which meaning is very clear:
    there may be "loss of data" if your position > 4294967295
    To fix it - don't use float, use u_long instead (or just ignore this warning!)

    2. This error is also very clear: compiler has no idea how to convert your struct data to 'u_long'.
    To fix it you could implement a union of this structure with a u_long variable. See the example in Union Declarations
    Victor Nijegorodov

  3. #3
    Join Date
    Apr 2001
    Posts
    1,029

    Re: endianness questions

    Hey Victor,

    2. But in the struct I only need access to one bit. Can I do something like this?

    Code:
    union               
    {                
       struct data
       {
           unsigned short int temp: 16;
           unsigned short int flag : 1;  
           unsigned short int temp2: 15;
       } dat;
        u_long data1;
    } dataun;
    
    bool flag_;
    memcpy(&dataun.dat, &message[4], 4);  
    dataun.data1=ntohl(dataun.data1);
    flag_=dataun.dat.flag;
    Is that correct?

    Also, why dont I see a "u_long" type on this site? http://msdn.microsoft.com/en-us/libr...tz(VS.80).aspx

    How big is a u_long as compared to a float?

    Thanks!
    Last edited by lab1; September 23rd, 2010 at 12:43 PM.

  4. #4
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Re: endianness questions

    Quote Originally Posted by lab1 View Post
    Also, why dont I see a "u_long" type on this site? http://msdn.microsoft.com/en-us/libr...tz(VS.80).aspx

    How big is a u_long as compared to a float?

    Thanks!
    u_long is presumably a typedef of unsigned long.

    Unfortunately, how large that is depends on the OS. On Windows (both 32-bit and 64-bit), it's 4 bytes, same as a float. But on 64-bit linux (and, I think, 64-bit OSX), an unsigned long is 8 bytes.

    If you want to write a generic ntoh(), you can do it:
    Code:
    template <typename T>
    T ntoh(T networkorder)
    {
        if (ntohs(1) == 1)
            return networkorder;
        char bytes[sizeof(T)];
        memcpy(bytes,&networkorder);
        std::reverse(bytes,bytes+sizeof(T));
        return *(reinterpret_cast<T*>(bytes));
    }
    There may be a better way to make this a pass-through in the cast of a BE machine, but it's at least possible that the if statement would be evaluated at compile time.
    Last edited by Lindley; September 23rd, 2010 at 12:53 PM.

  5. #5
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,398

    Re: endianness questions

    Quote Originally Posted by lab1 View Post
    2. But in the struct I only need access to one bit. Can I do something like this?
    ....
    Is that correct?
    Why didn't you try it?

    Quote Originally Posted by lab1 View Post
    Also, why dont I see a "u_long" type on this site? http://msdn.microsoft.com/en-us/libr...tz(VS.80).aspx

    How big is a u_long as compared to a float?
    Are you using a Microsoft compiler?

    And I guess u_long is 4 bytes long (i.e. 32 bit). It is the same as float but unsigned long can represent numbers between 0 and 4294967295 while float (according to MSDN) - between 1.175494351e-38F and 3.402823466e+38F
    Victor Nijegorodov

  6. #6
    Join Date
    Apr 2001
    Posts
    1,029

    Re: endianness questions

    Why does ntohl() return a unsigned long? What if the value is negative?

    Thanks

  7. #7
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Re: endianness questions

    Quote Originally Posted by lab1 View Post
    Why does ntohl() return a unsigned long? What if the value is negative?

    Thanks
    Once you start doing endianness conversions, the value doesn't matter anymore, only the bit pattern. The value of the bit pattern is only meaningful in the host byte order.

    If the value is intended to be negative, then casting the result to int should recover that.

  8. #8
    Join Date
    Apr 2001
    Posts
    1,029

    Re: endianness questions

    Hey Lindley,

    Why does this code end up with leTest as "227.0" then?

    Code:
    #include "winsock2.h"
    
    int main()
    {
        float test = -30.0;
        float beTest = htonl(test);
        float leTest = (float)ntohl(beTest);
    }
    By the way, the code is executed ona intel (little endian) machine.

    Thanks!
    Last edited by lab1; September 23rd, 2010 at 02:22 PM.

  9. #9
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Re: endianness questions

    Because conversion between floating types and integer types tries to preserve values rather than bit patterns. Try this instead:

    Code:
    #include "winsock2.h"
    
    int main()
    {
        float test = -30.0;
        unsigned long betest = htonl(*reinterpret_cast<unsigned long*>(&test));
        unsigned long letest = ntohl(betest);
        float leFloatTest = *reinterpret_cast<float*>(&letest);
    }

  10. #10
    Join Date
    Apr 2001
    Posts
    1,029

    Re: endianness questions

    That works. Can you explain why:

    Code:
        float leFloatTest = (float)letest;
    doesnt work? Why the weird casting?

    Also, any way I can condence these two lines into one line?

    Code:
        unsigned long letest = ntohl(betest);
        float leFloatTest = *reinterpret_cast<float*>(&letest);
    Thanks!
    Last edited by lab1; September 23rd, 2010 at 02:46 PM.

  11. #11
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    6,765

    Re: endianness questions

    Quote Originally Posted by lab1
    Can you explain why: (...) doesnt work? WHy the weird casting?
    Recall what Lindley wrote in post #7:
    Quote Originally Posted by Lindley
    Once you start doing endianness conversions, the value doesn't matter anymore, only the bit pattern.
    C + C++ Compiler: MinGW port of GCC
    Build + Version Control System: SCons + Bazaar

    Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
    Kindly rate my posts if you found them useful

  12. #12
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Re: endianness questions

    Quote Originally Posted by lab1 View Post
    Also, any way I can condence these two lines into one line?
    Sure, you can write a function:

    Code:
    template <typename To, typename From>
    static inline To bitwise_cast(From from) {
      BOOST_STATIC_ASSERT(sizeof(From) == sizeof(To));
      union {
        From f;
        To t;
      } u;
      u.f = from;
      return u.t;
    }

  13. #13
    Join Date
    Oct 2006
    Location
    Sweden
    Posts
    3,654

    Re: endianness questions

    Quote Originally Posted by lab1 View Post
    Code:
    struct data
    {
        unsigned short int temp: 16;
        unsigned short int flag : 1;  
        unsigned short int temp2: 15;
    } dat;
    Be aware that bitfields are not portable. If you use bitfields you have to be sure that the code on both sides have been compiled/linked with the same compiler/linker using the same flags and that the platforms are of the same type (CPU-family).
    Debugging is twice as hard as writing the code in the first place.
    Therefore, if you write the code as cleverly as possible, you are, by
    definition, not smart enough to debug it.
    - Brian W. Kernighan

    To enhance your chance's of getting an answer be sure to read
    http://www.codeguru.com/forum/announ...nouncementid=6
    and http://www.codeguru.com/forum/showthread.php?t=366302 before posting

    Refresh your memory on formatting tags here
    http://www.codeguru.com/forum/misc.php?do=bbcode

    Get your free MS compiler here
    https://visualstudio.microsoft.com/vs

  14. #14
    Join Date
    Apr 2001
    Posts
    1,029

    Re: endianness questions

    Quote Originally Posted by S_M_A View Post
    Be aware that bitfields are not portable. If you use bitfields you have to be sure that the code on both sides have been compiled/linked with the same compiler/linker using the same flags and that the platforms are of the same type (CPU-family).
    Where in the C++ Standard does it say this? I thought it said exactly the oppossite.

  15. #15
    Join Date
    Oct 2006
    Location
    Sweden
    Posts
    3,654

    Re: endianness questions

    I don't have access to a release version of the standard but here's a fragment from http://www.open-std.org/jtc1/sc22/wg...2005/n1905.pdf (section 9.6)
    A member-declarator of the form
    identifieropt : constant-expression
    specifies a bit-field; its length is set off from the bit-field name by a colon. The bit-field attribute is not part of the
    type of the class member. The constant-expression shall be an integral constant-expression with a value greater than or
    equal to zero. The constant-expression may be larger than the number of bits in the object representation (3.9) of the
    bit-field’s type; in such cases the extra bits are used as padding bits and do not participate in the value representation
    (3.9) of the bit-field. Allocation of bit-fields within a class object is implementation-defined. Alignment of bit-fields is
    implementation-defined. Bit-fields are packed into some addressable allocation unit. [ Note: bit-fields straddle allocation
    units on some machines and not on others. Bit-fields are assigned right-to-left on some machines, left-to-right on others.
    —end note ]
    Debugging is twice as hard as writing the code in the first place.
    Therefore, if you write the code as cleverly as possible, you are, by
    definition, not smart enough to debug it.
    - Brian W. Kernighan

    To enhance your chance's of getting an answer be sure to read
    http://www.codeguru.com/forum/announ...nouncementid=6
    and http://www.codeguru.com/forum/showthread.php?t=366302 before posting

    Refresh your memory on formatting tags here
    http://www.codeguru.com/forum/misc.php?do=bbcode

    Get your free MS compiler here
    https://visualstudio.microsoft.com/vs

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured