Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I reverse the byte order of an NSInteger or NSUInteger in objective-c

This is a somewhat of a follow up to this posting but with a different question so I felt I should ask in a separate thread.

I am at the point where I have four consecutive bytes in memory that I have read in from a file. I'd like to store these as a bit array (the actual int value of them does not matter until later). When I print out what is in my int, I notice that it seems to be stored in reverse order (little endian).

Does anyone have a good method for reversing the order of the bytes. Then once reversed, picking out consecutive bits spanning two bytes and converting back to an int?

unsigned char data[] = { 0x00, 0x02, 0x45, 0x28 };
NSInteger intData = *((NSInteger *)data);

NSLog(@"data:%08x", intData); // data:28450200
like image 302
Scott Avatar asked Sep 30 '10 13:09

Scott


People also ask

What is reverse byte order?

Description. The Byte Reversal block changes the order of the bytes in data that you input to the block. Use this block when a process communicates between target computers that use different endianness, such as between Intel® processors that are little endian and other processors that are big endian.

Why are bytes reversed?

Bits and Bytes need to be reversed quite often. Some computers store data in a little-endian format and some in a big-endian format. In order for communication between these two hosts to work, these conversions must be done with extreme precision.


1 Answers

Cocoa (or to be exact the Foundation framework) has functions to swap the endianness of bytes: NSSwapInt, NSSwapShort, NSSwapLong, and NSSwapLongLong. These swap around the bytes no matter what - they make big-endian integers from small-endian integers and vice versa.

If you know which format you have there are other functions that swap it to the native endianness: NSSwapLittleIntToHost and NSSwapBigIntToHost. There are also the reverse functions which swap from the native format to little or big endian format: NSSwapHostIntToLittle and NSSwapHostIntToBig. Those are available for the other integer types and floating point types as well. What they do is they call the primitive swap functions on the values if necessary. So NSSwapLittleIntToHost doesn’t do anything while NSSwapBigIntToHost returns the result of NSSwapInt on a little endian machine.

Note that these take parameters of the compilers integer types and not the NSInteger type. So depending on wether you’re generating 32bit or 64bit code you have to use different functions if you are using NSInteger.

You also should not cast your byte array to an integer pointer and dereference that. It would be better to assemble the integer using bit shift operations. Your code will only work if NSInteger is 32 bit wide. If it is 64 bit then your number will be garbage or your program might even crash. But even if you are using an integer type that is always 32 bit wide (int32_t from the C99 <stdint.h> header for example) this might not work as expected.

like image 192
Sven Avatar answered Sep 22 '22 19:09

Sven