1

Maybe I don't find other functions, but all functions that deals with endianness that I find accept only unsigned variable. My question is why (or are there functions that deals with endianness and accept signed variable) ?

List of functions I find : here and here.

Maybe solution is to use these macro ? What is the difference between macro and above function ?

romaric crailox
  • 564
  • 1
  • 3
  • 15
  • Signedness is implementation-defined, and signed integers should not be used to store maps of bits. Still, if you need to do that for a specific reason, why not just cast your `int` to its `unsigned` equivalent first? – underscore_d Aug 03 '17 at 12:40
  • Since you are talking about implementations, it would be valid to bit cast the signed to unsigned (some way of type punning) change the endianness and bit cast it back. – Ajay Brahmakshatriya Aug 03 '17 at 12:41
  • @underscore_d yes, signedness is implementation-defined, but so is endianness. I think it is OK to assume that OP is referring to a particular implementation. – Ajay Brahmakshatriya Aug 03 '17 at 12:42
  • Possible duplicate of [How do I byte-swap a signed number in C?](https://stackoverflow.com/questions/10435665/how-do-i-byte-swap-a-signed-number-in-c) – underscore_d Aug 03 '17 at 12:42
  • @underscore_d simply casting might not be enough, since the sign information can get lost. – Ajay Brahmakshatriya Aug 03 '17 at 12:43
  • @AjayBrahmakshatriya So, by "bit cast", you mean reinterpret via an `unsigned` pointer, rather than casting the value? – underscore_d Aug 03 '17 at 12:43
  • @underscore_d using a pointer would lead to violation of strict aliasing. He can create another unsigned variable (of same size), memcpy the bytes and reverse after changing the endianness. – Ajay Brahmakshatriya Aug 03 '17 at 12:45
  • 1
    @AjayBrahmakshatriya I think that's incorrect as aliasing rules make an allowance for _"a type that is the signed or unsigned type corresponding to the dynamic type of the object"_. For a non-corresponding type, I would agree. Either way, it's always better to be _too_ paranoid about aliasing, than not paranoid enough. :D – underscore_d Aug 03 '17 at 12:46
  • 1
    @underscore_d I agree. I completely missed that point. Either way, I answered the question using `unions`. I am most comfortable with those. – Ajay Brahmakshatriya Aug 03 '17 at 12:53

1 Answers1

2

Since endianness is implementation defined, it is safe to assume that you are talking about an implementation and not C standard. Looking at the links you have sent, I think you refer to Linux and GNU C compiler.

Then under this implementation it is safe to first type pun the signed int to unsigned int, change the endianness and type pun it back.

Following is one way of doing it

union signed_unsigned {
    signed long a;
    unsinged long b;    
} converter;


signed long to_convert = .... //whatever value

converter.a = to_convert;
converter.b = htonl(converted.b);
to_convert = converter.a;

You can make this into a macro or a function as you see fit.

As suggested by @underscore_d, the other way to type pun a signed long to unsigned long (and back) is using pointer cast. That is valid in both C and C++ (although in C++ you should use reinterpret_cast rather than C style pointer casts).

You can use the following way to achieve the same.

signed long to_convert = .... //whatever value
unsigned long temp = *(unsinged long*)&to_convert;
temp = htonl(temp);
to_convert = *(signed long*)&temp;
Ajay Brahmakshatriya
  • 8,993
  • 3
  • 26
  • 49
  • In case anyone lands here and wants to use this in C++, note that type-punning via a `union` is only allowed (albeit potentially trapping) in C, not C++, whereas reinterpreting as the corresponding un/signed type will work in both (as it is allowed by the aliasing rules). – underscore_d Aug 03 '17 at 12:55
  • Yes it is on linux with gcc compiler. Thanks for these answers. – romaric crailox Aug 03 '17 at 13:37