我的问题非常疯狂,但是听着我像这样int a,b
创建了两个普通变量,然后将b
变量的地址分配给了a
,并在打印地址时a
和&b
都显示一个随机数,但两者相同。
怎么可能?
而a
不是指针变量。
int main()
{
int a,b;
a = &b;
printf("%u %u",a,&b);
return 0;
}
I got a number that must be address and both are same.
答案 0 :(得分:4)
如果使用C编译器编译了此程序,则要求编译器警告您a = &b;
中的类型错误,因为它违反了分配约束。你收到警告了吗?您忽略了吗?
在编译器警告您之后,它大概为a = &b;
生成了将&b
类型的int *
转换为int
类型的代码。在某些C实现中,int
可以保存int *
的所有信息,并且转换以简单的方式进行。在某些C实现中,int
太小,无法容纳int *
的所有信息。
printf("%u %u",a,&b);
使用了错误的说明符。 %u
用于unsigned int
,但是a
是int
,而b
是int *
。当使用了错误的说明符时,C标准没有定义结果。
尽管缺乏定义,但您的C实现很有可能会打印a
的值,就好像它已转换为unsigned int
一样,并且它可能做了相同的事情与&b
。这将导致输出两个相同的数字。由于违反了上述有关说明符的规则,因此该结果不可靠。
如果您的实现确实以通用方式定义了指向int
的指针的转换,并且int
的宽度足以容纳int *
的所有信息,那么编写程序的正确方法是:
#include <stdio.h>
int main(void)
{
int a, b;
a = (int) &b;
printf("%#x %p\n", (unsigned) a, (void *) &b);
}
不能保证这两个值显示相同的输出字符串,尤其是因为%p
是灵活的-精确的格式是实现定义的,因此在C实现中可能有所不同。但是它们在许多C实现中都是相同或相似的。
通常,指针不应转换为整数。但是,有时需要这样做,例如编写必须以特殊方式处理地址的内核代码或编写必须处理对齐问题的高性能代码时。在这种情况下,比起使用int
更好的解决方案是包含<stdint.h>
并使用uintptr_t
。 uintptr_t
是无符号整数类型,适用于从指针转换为指针。
答案 1 :(得分:1)
普通变量可以保存另一个变量的地址吗?
是的(也许)。
编译器通常将源代码转换为目标CPU的机器代码。对于CPU的机器码(几乎所有CPU)来说,没有类型-一切(所有指令,所有指针,所有整数,所有浮点数等)只是位模式;而CPU不知道(内存或寄存器中的)位模式是地址,整数还是其他。
这意味着,如果您可以说服编译器将指针存储为整数,则CPU本身将不会知道或不在乎。
对于C;通过执行int
并忽略任何警告,很容易说服编译器将指针存储在a = &b;
中。或通过执行a = (int)&b;
来抑制警告。当然,这将不是可移植的,并且值可能会被调整为适合(例如,如果指针是64位,而int
是32位,则可以预期将丢弃一半的指针以使该值适合int
)。