我正在查看同学发布的一些代码,为了这个例子,它已被简化:
int main()
{
int n = 0x4142;
char * a = (char *) &n;
char * b1 = (((char *) &n) + 1);
char * b2 = (((int) &n) + 1);
printf("B1 Points to 0x%x - B2 Points to 0x%x\n", b1, b2);
printf("A Info - 0x%x - %c\n", a, *a);
printf("B1 Info - 0x%x - %c\n", b1, *b1);
printf("B2 Info - 0x%x - %c\n", b2, *b2);
return 0;
}
输出结果为:
B1 Points to 0xcfefb03d - B2 Points to 0xcfefb03d
A Info - 0xcfefb03c - B
B1 Info - 0xcfefb03d - A
Segmentation fault (core dumped)
尝试打印b2时出现分段错误。而我认为输出应该包括以下行而不是seg faulting:
B2 Info - 0xcfefb03d - A
为什么会这样? b1和b2都是char *,它们都指向相同的地址。这是在64位机器上,其中sizeof(char *)== 8和sizeof(int)== 4,如果这很重要。
答案 0 :(得分:3)
但它在64位计算机上出现了段错误
可能的原因是,在您的平台上,指针是64位,而int是32位。因此,当您将指针转换为int
时,您将丢失信息。
我的编译器特别警告:
test.c:7:19: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
使用以下程序很容易看到:
#include <stdio.h>
int main()
{
char *s = "";
printf("%p %p\n", s, (char*)(int)s);
return 0;
}
在我的电脑上,这会打印两个不同的地址(第二个地方的顶部位被切掉)。
我不太明白,b1和b2都是char *,它们都指向同一个地址
实际上,他们并没有指向相同的地址。您的printf()
格式说明符都错了。第一个printf()
应为:
printf("B1 Points to %p - B2 Points to %p\n", b1, b2);
当你运行它时,你会看到地址不同。
答案 1 :(得分:1)
(int)&n
可能会将n
的地址截断为int
,IOW中的位数(通常是这种情况)在64位CPU上,你会得到一个虚假的,截断的地址/指针,你不能安全地取消引用。
答案 2 :(得分:1)
在您的示例中,由于int
为4个字节,因此在您投射&n
并尝试将其分配给b2
时会截断uintptr_t
的值。要将指针值视为整数,请使用char * b2 = (((int) &n) + 1);
,这是一种无符号整数类型,无论平台容量如何,都可以安全地存储指针:
char * b2 = ((uintptr_t) &n) + 1;
应该是:
{{1}}