假设我有一个uint8_t
指针指向数组中的第三个元素{1,2,4,5},所以*p
是4.我怎样才能指向4和5使*p
为45.甚至可能吗?我目前正在进行类型转换。这是我做的事情,例如如果数据是我的数组{1,2,4,5},我想获得4和5。
uint8_t dummyAddress = data[2];
dummyAddress = *((uint16_t*) dummyAddress);
*p = *dummyAddress;
我的理解是p现在应该指向4和5,但我不是。相反,当我执行第二行时,我遇到了一个段错误。 p是uint64_t * const
。它可以获得一个字节,但是当将相同的逻辑应用于两个字节时,我没有把它弄好。
答案 0 :(得分:4)
你可以这样做:
uint8_t data[] = { 1, 2, 4, 5 };
uint8_t *p8 = &data[2];
uint16_t u16 = *(uint16_t*)p8;
然后(uint16_t*)p8
将指向data[2]
和data[3]
。但您无法轻松访问*(uint16_t*)p8
。首先,这是因为p8
可能未在uint16_t
边界上对齐。某些处理器在这种情况下会导致异常。其次,即使您可以访问*(uint16_t*)p8
,也可能会得到不同的结果,具体取决于处理器的字节顺序(big endian / little endian)。您可能会得到0x0405,或者您可能会得到0x0504。
请注意您的行
dummyAddress = *((uint16_t*) dummyAddress);
您首先将dummyAddress
重新解释为uint16_t
的指针然后取消引用它,因此返回uint16_t
并将其存储在dummyAddress
中。这显然不是你想要做的。如果这确实编译了,请考虑使用更高的警告级别编译并查看每个编译器警告(如果您理解它并且确定它不是编程错误,则忽略它)。
p
的{{1}}指针。
另外,正如mch所说:What is the strict aliasing rule?
答案 1 :(得分:1)
如果我理解你在做什么,那么是的,你可以通过转换为uint16_t
来访问这两个字节,但是你会遇到问题(或者字节序问题)以及字节在内存中的存储顺序以及违反严格别名。这可能会返回您不怀疑的答案。例如:
#include <stdio.h>
#include <stdint.h>
int main (void) {
uint8_t array[] = {1,2,3,4};
uint8_t *p = array + 2;
printf ("\n the uint8_t answer : %hhd\n", *p);
printf (" the uint16_t answer : %hd\n\n", *(uint16_t *)p);
printf ("**note: the will cast result in bytes 4, 3"
" (or (4 << 8 | 3) = 1027)\n\n");
return 0;
}
<强>输出强>
$ ./bin/cast_array
the uint8_t answer : 3
the uint16_t answer : 1027
**note: the cast will result in bytes 4, 3 (or (4 << 8 | 3) = 1027)
字节以little endian
顺序存储在我的系统内存中。因此,当您转换为uint16_t
时,它希望找到least significant
,most significant
个字节。在上面的示例中,内存中有34
,演员会将实际订单解释为43
,从而导致值为1027
而不是(3 << 8) | 4 = 772
。
如上所述,您将违反与严格别名相关的规则,其中通过强制转换为char
以外的任何内容进行类型修剪会导致未定义的行为。所有这些操作的结果都依赖于硬件和编译器,不应用于学习练习以外的任何其他操作。
答案 2 :(得分:0)
你应该写:
*p==45
但请注意,由于&#34; endianness&#34;您可能会以错误的顺序获得两个uint_8_t *dummyAddress= &data[2];
uint_16_t *dummyAddress2= (uint16_t *) dummyAddress;
uint_16_t p= *dummyAddress2;
,即uint_8
。