为什么uint8_t在分配给解除引用的uint32_t指针时会占用4个字节?

时间:2014-07-30 05:19:43

标签: c++ c pointers memory-management dereference

在为取消引用的4字节指针分配字节值时,我的应用程序中出现了错误:

uint8_t value = 5;
uint8_t myArray [4] = {1,2,3,4};
uint32_t *myPointer = &myArray[0];

*myPointer = value; // myArray is now {5,0,0,0}
//*(uint8_t*)myPointer = value; // works correctly, myArray: {5,2,3,4}

在我看来,这是一个非常讨厌,难以察觉的错误,即使所有警告都打开,编译过程中也不会出现警告。为什么编译器没有处理这个问题,因为value的大小是显而易见的?此外,我虽然指针大小的概念与指向更高地址的能力相关,而不是实际分配了多少内存。

4 个答案:

答案 0 :(得分:4)

编译器会在您犯错时警告您:

uint32_t *myPointer = &myArray[0];

(...)

und.c:8:11: warning: incompatible pointer types initializing 'uint32_t *'
      (aka 'unsigned int *') with an expression of type 'uint8_t *'
      (aka 'unsigned char *') [-Wincompatible-pointer-types]

您选择将值重新解释为整数,这会导致未定义的行为。在此之后,您尝试重新解释第二次,忽略了您分配给整数的事实。但现在你陷入了C弱键入规则:你可以隐式地从uint8_t转换为uint32_t而不会发出警告。如果你想要它,C会做到。

答案 1 :(得分:3)

  

为什么编译器不处理这个

因为你得到你写的东西!

如果为32位存储分配值,则将访问32位存储。如果你说:

,那就是你写的
uint32_t *myPointer

如果需要8位值,请使用指向8位值的指针!

编译器负责这一切!但是你不能将8位值写入指向32位值的指针。这导致从8位值转换为32位值!

 uint8_t val;
 uint32_t *myPointer;
 *myPointer = val;

结果:

 *myPointer = ( uint32_t ) val;

答案 2 :(得分:1)

赋值运算符分配给左侧,右侧的值。左侧的先前值被忽略。实际上它甚至都没有从内存中检索出来。

示例:

int a = 0x12345678;
a = 7;
cout << a << "\n";   // outputs 7

我不知道这是一个令人讨厌的错误&#34;一点都不。

如果你在谈论类类型,那么赋值运算符可能会被重载以保留左侧的部分原封不动(尽管这可能是一个糟糕的设计)。但对于原始类型,赋值甚至不检索分配给的内存位置的内容;它只写了新的内容。

如果右侧操作数的类型不匹配,则将其转换为左侧的类型。例如:

int a = 0x12345678;
double d = 6.5;

a = d;

cout << a << "\n";     // outputs 6

我不确定在这种情况下你应该输出什么。

在某些编程语言中,没有隐式转换,您必须编写a = (int)d;

无论好坏,C和C ++都不属于这些语言;并且您可以隐式地在算术类型之间进行转换。有些编译器会对潜在的缩小转换率发出警告,但没有人会警告&#34;扩大转换次数&#34;。

答案 3 :(得分:0)

这是值如何存储在内存中以及隐式转换发生的结果。概率为99.9%,您使用的是小型字节序处理器,如Intel或ARM,这意味着多字节类型的字节(如32位整数)以相反的顺序存储。如何存储32位int是相关的,因为8位value在分配给*myPointer(32位整数)时被隐式转换为32位int。当整数5存储在小端处理器上时,它会反转字节顺序。因此,最低有效字节5存储在myArray[0]中,而更高有效字节0被分配给myArray[1]myArray[2]myArray[3]