Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is pointer arithmetic inconsistent across architectures?

Given the following code:

unsigned char *packet_data = (unsigned char *)malloc(7);
memset(packet_data, 0, 7);

uint16_t crc = 0xa8a9;

*((uint16_t *)&packet_data[5]) = (crc >> 8) | (crc << 8);

for (int i = 0; i < 7; i++) {
        printf("%02X ", packet_data[i]);
}
printf("\n");

On my Mac (x86_64), the output is, as expected, 00 00 00 00 00 A8 A9 (A8 goes in byte 5 (counting from 0)). Compiled with clang (LLVM 7.3.0)

On an armv5tejl machine, the output is, however, 00 00 00 00 A8 A9 00 (A8 goes in byte 4 (counting from 0)). In this case, if we switch 5 to 4 on the source code the exact same output will come out. Compiled with gcc 4.6.3, like this on the Godbolt compiler explorer.

Both machines are little endian.

Why does this happen?

like image 662
Matoe Avatar asked Sep 20 '26 03:09

Matoe


1 Answers

Assuming alignment requirement for the type uint16_t is 2, then your code has undefined behavior1, as this pointer: (uint16_t *)&packet_data[5] isn't correctly aligned.

If you use an aligned offset, like 4, the results should be the same as the behavior is defined.


1 (Quoted from: ISO/IEC 9899:201x 6.3.2.3 Pointers 7):
A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned for the referenced type, the behavior is undefined.

like image 150
2501 Avatar answered Sep 22 '26 19:09

2501



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!