Question

Say I have the following:

int32 a = ...; // value of variable irrelevant; can be negative
unsigned char *buf = malloc(4); /* assuming octet bytes, this is just big 
                          enough to hold an int32 */

Is there an efficient and portable algorithm to write the two's complement big-endian representation of a to the 4-byte buffer buf in a portable way? That is, regardless of how the machine we're running represents integers internally, how can I efficiently write the two's complement representation of a to the buffer?

This is a C question so you can rely on the C standard to determine if your answer meets the portability requirement.

Was it helpful?

Solution

Yes, you can certainly do it portably:

int32_t a = ...;
uint32_t b = a;
unsigned char *buf = malloc(sizeof a);

uint32_t mask = (1U << CHAR_BIT) - 1;  // one-byte mask

for (int i = 0; i < sizeof a; i++)
{
    int shift = CHAR_BIT * (sizeof a - i - 1); // downshift amount to put next
                                               // byte in low bits
    buf[i] = (b >> shift) & mask;  // save current byte to buffer
}

At least, I think that's right. I'll make a quick test.

OTHER TIPS

unsigned long tmp = a; // Converts to "twos complement"
unsigned char *buf = malloc(4);
buf[0] = tmp>>24 & 255;
buf[1] = tmp>>16 & 255;
buf[2] = tmp>>8 & 255;
buf[3] = tmp & 255;

You can drop the & 255 parts if you're assuming CHAR_BIT == 8.

If I understand correctly, you want to store 4 bytes of an int32 inside a char buffer, in a specific order(e.g. lower byte first), regardless of how int32 is represented.

Let's first make clear about those assumptions: sizeof(char)=8, two's compliment, and sizeof(int32)=4.

No, there is NO portable way in your code because you are trying to convert it to char instead of unsigned char. Storing a byte in char is implementation defined.

But if you store it in an unsigned char array, there are portable ways. You can right shift the value each time by 8 bit, to form a byte in the resulting array, or with the bitwise and operator &:

// a is unsigned
1st byte = a & 0xFF
2nd byte = a>>8 & 0xFF
3rd byte = a>>16 & 0xFF
4th byte = a>>24 & 0xFF
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top