为什么这个 uint32_t 转换在 iPhone 模拟器和 iPhone 设备上表现不同?
Why does this uint32_t cast behave differently on iPhone simulator and iPhone device?
为什么以下代码在 iPhone 模拟器和设备上表现不同?我 运行 intel macbook pro 上的模拟器,设备是 iPhone 5(型号 MD297KS/A)。
代码:
uint8_t original = 23;
uint8_t * pointerToOriginal = &original;
uint32_t * casted = (uint32_t *)pointerToOriginal;
printf("original: %u\ncasted: %u\n", original, *casted);
模拟器上运行时的输出:
original: 23
casted: 23
设备上 运行 时的输出:
original: 23
casted: 2755278871
我假设转换会导致转换的整数中包含垃圾数据,因此设备输出对我来说有意义,但是 为什么整数不受引入的额外数据的影响在模拟器上投射?
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. ...
The behavior is undefined in the following circumstances: ...
- Conversion between two pointer types produces a result that is incorrectly aligned (6.3.2.3).
强调我的
首先你的代码会导致未定义的行为。
但为了清楚起见,我将尝试解释发生了什么。
original
存储在堆栈中。因此,当您获取指向 original
的指针时,您将获得指向堆栈内存中长度为 8 位的区域的指针(此信息仅适用于编译器)。像这样:
byte 0 byte 1 byte 2 byte 3
[00010111][????????][????????][????????]
假设堆栈从地址 0 开始。
所以 pointerToOriginal
将指向地址 0 处的字节。编译器知道 pointerToOriginal
指向 8 位值(因为它的类型)。因此,当取消引用时,它将从地址 0 开始准确读取 1 个字节。
但是,当将 uint8_t*
转换为 uint32_t*
时,您实际上强制编译器读取 4 个字节而不是 1 个字节。因此您最终将读取 4 个字节,其中 3 个字节将成为垃圾。
在模拟器上,内存区域看起来像是填满了零。所以堆栈看起来像这样:
byte 0 byte 1 byte 2 byte 3
[00010111][00000000][00000000][00000000]
当您取消引用 casted
时,您将得到 23。但在真机上它只会包含垃圾。
上面的插图没有解释更高级的东西 - Big and Little Endian。
为什么以下代码在 iPhone 模拟器和设备上表现不同?我 运行 intel macbook pro 上的模拟器,设备是 iPhone 5(型号 MD297KS/A)。
代码:
uint8_t original = 23;
uint8_t * pointerToOriginal = &original;
uint32_t * casted = (uint32_t *)pointerToOriginal;
printf("original: %u\ncasted: %u\n", original, *casted);
模拟器上运行时的输出:
original: 23
casted: 23
设备上 运行 时的输出:
original: 23
casted: 2755278871
我假设转换会导致转换的整数中包含垃圾数据,因此设备输出对我来说有意义,但是 为什么整数不受引入的额外数据的影响在模拟器上投射?
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. ...
The behavior is undefined in the following circumstances: ...
- Conversion between two pointer types produces a result that is incorrectly aligned (6.3.2.3).
强调我的
首先你的代码会导致未定义的行为。 但为了清楚起见,我将尝试解释发生了什么。
original
存储在堆栈中。因此,当您获取指向 original
的指针时,您将获得指向堆栈内存中长度为 8 位的区域的指针(此信息仅适用于编译器)。像这样:
byte 0 byte 1 byte 2 byte 3
[00010111][????????][????????][????????]
假设堆栈从地址 0 开始。
所以 pointerToOriginal
将指向地址 0 处的字节。编译器知道 pointerToOriginal
指向 8 位值(因为它的类型)。因此,当取消引用时,它将从地址 0 开始准确读取 1 个字节。
但是,当将 uint8_t*
转换为 uint32_t*
时,您实际上强制编译器读取 4 个字节而不是 1 个字节。因此您最终将读取 4 个字节,其中 3 个字节将成为垃圾。
在模拟器上,内存区域看起来像是填满了零。所以堆栈看起来像这样:
byte 0 byte 1 byte 2 byte 3
[00010111][00000000][00000000][00000000]
当您取消引用 casted
时,您将得到 23。但在真机上它只会包含垃圾。
上面的插图没有解释更高级的东西 - Big and Little Endian。