如何使指针指向两个或多个连续的单元格

时间:2015-11-03 16:51:40

标签: c pointers

假设我有一个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。它可以获得一个字节,但是当将相同的逻辑应用于两个字节时,我没有把它弄好。

3 个答案:

答案 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 significantmost 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