long integers and byte order

I was preparing to send some bits down a serial port and I did a very simple thing. The bits were defined in a long int like this: long int lngint=19114957L;
The hex representation of this string is, of course: 0123ABCD.

I then did some gyrations to cast this string into a char array so that I could send it down the port:

long int *liptr;
char *cptr;
char port_buffer[80];
liptr=&lngint;

cptr=(char*)liptr;
strncpy(port_buffer,cptr,4);

Things did not go as planned and after dumping the program, I found that the value stored in lngint, as as follows:

CD AB 23 01

The resulting character string of course, flew down the port backwards!

Clearly for this compiler/processor the highest addressed byte contains the most significant digits of the long int. Now-I can load the port_buffer array by hand, byte by byte, reversing the order. But this may not be a good idea. Perusing the few C books I have it appears that there is no standard as to how byte order for a long int is stored on a processor. I am using 186 platforms. Is the byte order conserved with other processors? I know that at least when dealing with discrete semiconductor components, bit ordering is not always consistent.

Perusing the few C books I have it appears that there is no standard as to how byte order for a long int is stored on a processor. I am using 186 platforms.

There are standards WRT byte order, two of them. Guess what they are ?

The order for x86, as you've just discovered, is little endian.

Is the byte order conserved with other processors?

Historically a lot of network servers used a (non-x86) architecture with big endianian byte order, hence it is sometimes called "network byte order" and it still the norm in networking, so there are networking library functions to convert.

There are standards WRT byte order, two of them. Guess what they are ?

The order for x86, as you've just discovered, is little endian.

You got the number wrong: there are more than two real-world byte orders. Look up "middle endian".

There are also some hardware architectures that are bi-endian, meaning they can be configured to different endianness in data segments and/or code segments.

Right 98% of the time, and don't care about the other 3%.

If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

Very often the easiest way to convert is to use sprintf() when sending and sscanf() when receiving... it eliminates the whole endian thing quite nicely.

Most likely endianness actually isn't really an issue -- there are no conversions necessary, just the OP was unaware that the bytes in an int are the reverse of what you might assume.

Using offsets into a bytes stream and casting to type, or just reading the whole thing into a struct, is easier and faster than using string functions (and definitely more conventional). If you do need a conversion, as you mention there are simple functions for that.

Originally Posted by grumpy

You got the number wrong: there are more than two real-world byte orders.

I stand corrected! What we really need for a proper challenge is indeterminate byte ordering.

Some ISO 8583 communications protocols (used for authorisation of financial transactions) are middle-endian. Processors in embedded systems that natively use such protocols (such as POS systems) will either be middle-endian or emulate middle-endian behaviour. There are a few of those around in the modern world.

Right 98% of the time, and don't care about the other 3%.

If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

Thanks for the replies. I gained my expertise (now long gone!) on Univacs, 370s and Solaris. I am pretty sure these were big-endian. I will play it safe and not rely on an given byte order as my code will probably get ported to 6800 processors and perhaps some ARM devices.

I did not find any functions that simply take a long int and convert it directly into a char string in proper order. There are a few conversions on the FAQ for this forum but not for this purpose.

I did not find any functions that simply take a long int and convert it directly into a char string in proper order. There are a few conversions on the FAQ for this forum but not for this purpose.

That's why I mentioned sprintf() and sscanf() ... The idea is pretty simple, a string is a series of bytes, they have no endian issues so if you take your value --lets say 123--- and covert that to a string with sprintf() and send it, it goes out in byte order left to right... the other end gets "123", now you convert that from a string to an int with sscanf() on the target machine... sscanf() will write the value to an int *in the correct endian orientation for that machine* ... now you don't have to worry about big endian, little endian, whatever... in fact you don't even need to know... because the int to string to int conversion takes care of it for you.

I did not find any functions that simply take a long int and convert it directly into a char string in proper order.

Depends what you mean by "proper order".

One option is using sprintf() and scanf().

Another option - assuming you are only attempting to move 16 and 32 bit unsigned integers between systems, and are happy to transmit them in a binary format - is use of functions that convert to and from network byte order. Look up functions named htons(), htonl(), ntohs(), and ntohl(). Virtually all systems that support IP networking support these functions in some way (although these functions are not standard C, so you will have to read documentation for your compiler and/or host system).

Right 98% of the time, and don't care about the other 3%.

If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

One thing that I didnt' mention is that the receiving machine is a spectrometer-I don't have access to its code etc. The compiler/microprocessor that I am using does not support htonxx() routines.

I am not sure that sscanf and ssprintf are useful here. I am not dealing with ASCII. For example I need to send the spectrometer a 4 byte buffer that contains a time delay. My code after many gyrations calculates this delay as a long int. Thus my process to sendthe device a time delay of: 6844 would be:

One thing that I didnt' mention is that the receiving machine is a spectrometer-I don't have access to its code etc. The compiler/microprocessor that I am using does not support htonxx() routines.

I am not sure that sscanf and ssprintf are useful here. I am not dealing with ASCII. For example I need to send the spectrometer a 4 byte buffer that contains a time delay. My code after many gyrations calculates this delay as a long int. Thus my process to sendthe device a time delay of: 6844 would be:

This will work in both directions... you can assign an integer value to W and read individual bytes out of B in any order you want. You can also assign bytes to B and read the DWORD value from W.... A little experimentation should help you decide if you want to read/write B as 0, 1, 2, 3 or 3, 2, 1, 0... so you now have full control over the endianness of the communications...

If the values you supplied are correct, then you will need to swap a couple of nibbles (a nibble is half a byte) relative to this. Assuming you only want to swap the 1 in the second byte (outbuf[1]) and the zero in the third byte (outbuf[2]) then ...

The magic value here, 0x10 is 0xF + 1 (i.e. 16). Assuming an unsigned char has a range 0-255, dividing by 16 extracts the upper nibble, and modulo 16 extracts the lower nibble of a char. Then you just need to rebuild two characters with the nibbles swapped as needed.

This is not the only way to produce the bytes you suggest from a value 6844. If I've got the order wrong (check what other values should produce) then you will need to adjust.

If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.