我写了一段非常简单的C代码:
int main(void) {
void *area = malloc(2 * sizeof(int));
unsigned int *int_one = (unsigned int *) area;
unsigned int *int_two = ((unsigned int *) area) + 3;
*int_two = 4293422034;
*int_one = 2;
printf("%u\n%u\n", *int_two, *int_one);
return 0;
}
sizeof(int)
在我的计算机上是4
。根据我的理解,修改地址int_one
上的内存不应该影响存储在地址int_two
上的值吗?
修改*int_one
会更改内存的前4
个字节。地址area
(也许不是全部为4,但是足以保证我期望的结果吗?),地址int_two
处的整数从整数int_one
的最后一个字节开始。 >
因此,更改int_one
处的内存不应该对int_two
处的内存有影响吗?
然而,printf
调用分别产生4293422034
和2
。
我确保使用无符号变量来避免2s补数和负值之间的混淆,并为*int_one
使用一个小的值来保证其最后一个字节的变化(不知道这是否正确? )
我没有得到什么?
答案 0 :(得分:3)
运算符'+'应用于指针时,会将指针n
增大为其所指向对象的大小。因此,将int*
增加3
不会增加3个字节,而是增加3*sizeof(int)
个字节。
答案 1 :(得分:2)
指针算术按指针指向的类型的大小缩放。 (在您的情况下为sizeof(unsigned int)
)。如果您想将地址增加3个字节,则需要在添加3之前强制转换为(char*)
,但是将其转换为unsigned*
指针将导致违反 undefined behavior 的行为对齐要求(6.3.2.3p7)和取消引用指针会违反严格的别名规则(6.5p7),从而使程序“更加不确定”。
要真正实现这种类型的校正,您需要使用memcpy
(或union
s)。
示例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
void *area = malloc(2 * sizeof(int));
if(!area) return EXIT_FAILURE;
unsigned int *int_one_p = area;
void *int_two_p = (((char*) area) + 3); /*saving this to an (unsigned*) would be UB*/
memcpy(int_two_p,&(unsigned){4293422034},sizeof(unsigned));
memcpy(int_one_p,&(unsigned){2},sizeof(unsigned));
unsigned one,two;
memcpy(&one,int_one_p, sizeof(one));
memcpy(&two,int_two_p, sizeof(two));
printf("%u\n%u\n", two, one);
return 0;
}