float指针和int指针地址有什么区别?
我试着运行这段代码,
int *p; float q; q = 6.6; p = &q;
虽然这将是一个警告,但我认为&q
和p
具有相同的大小,所以p
可以具有q
的地址。 但是当我打印&q
和p
我得到不同的输出。 这是我的输出
*p = 6.600000 q = 0.000000, p = 0x40d33333, &q = 0x7fffe2fa3c8c
我错过了什么? 当指针和变量类型相同时, p
和&q
相同。
我的完整代码是
#include void main() { int *p; float q; q = 6.6; p = &q; printf("*p = %f \nq = %f, p = %p, &q = %p \n",*p,q,p,&q); }
您需要更严肃地对待编译器警告。
C不要求编译器拒绝无效程序,它只需要“诊断”来规则违规。 诊断可以是致命错误消息或警告。
不幸的是,编译器通常会为不兼容的指针类型的分配发出警告。
void main()
这是错的; 它应该是int main(void)
。 您的编译器可能会让您逃脱它,并且它可能不会导致任何明显的问题,但是没有正确编写它没有意义。 (它不是那么简单,但那已足够接近了。)
int *p; float q; q = 6.6;
没关系。
p = &q;
p
的类型为int*
; &q
的类型为float*
。 将一个分配给另一个(没有强制转换)是违反约束的 。 看待它的最简单方法是它完全是非法的。
如果你真的想做这个任务,你可以使用强制转换:
p = (int*)&q; /* legal, but ugly */
但这样做的理由很少。 p
是指向int
的指针; 它应该指向一个int
对象,除非你有一个很好的理由让它指向别的东西。 在某些情况下,转换本身可能具有未定义的行为。
printf("*p = %f \nq = %f, p = %p, &q = %p \n",*p,q,p,&q);
%f
格式需要一个double
参数(在此上下文中float
参数被提升为double
,因此float
可以正常)。 但*p
的类型为int
。 使用错误类型的参数调用printf
会导致程序的行为未定义。
%p
需要一个类型为void*
的参数,而不仅仅是任何指针类型。 如果要打印指针值,则应将其void*
为void*
:
printf("&q = %p\n", (void*)&q);
它可能在没有演员的情况下工作,但同样,行为是不确定的。
如果在编译程序时收到任何警告,请不要打扰它。 首先修复警告。
至于标题中的问题, int*
和float*
类型的指针有不同的类型。 int*
应该指向一个int
对象; float*
应该指向一个float
对象。 您的编译器可能会让您混合它们,但这样做的结果是实现定义或未定义。 C语言,特别是许多C编译器,可以让你逃避许多没有多大意义的事情。
它们是不同类型的原因是(试图)防止或至少检测其使用中的错误。 如果声明int*
类型的对象,则表示您打算将其指向int
对象(如果它不是空指针)。 在int*
对象中存储float
对象的地址几乎肯定是一个错误。 强制类型安全性允许尽早检测到此类错误(当您的编译器打印警告时,而不是在重要客户端的演示期间程序崩溃时)。
很可能(但不能保证) int*
和float*
具有相同的大小并且具有相同的内部表示。 但是int*
对象的含义不是“包含虚拟地址的32(或64)位的集合”,而是“指向int
对象的东西”。
您将获得未定义的行为,因为您将错误的类型传递给printf
。 当你告诉它期望浮动时,它实际上需要一个double
– 但你传递一个int
。
因此,它会输出错误的信息,因为printf
完全依赖于格式字符串来访问传递它的参数。
除了teppic所说的,
考虑,
int a = 5; int *p = &a;
在这种情况下,我们向编译器指出p
将指向一个整数。 所以众所周知,当我们在运行时执行类似*p
的操作时,不会。 将读取等于int
大小的字节数。
如果将占用x
个字节数的数据类型的地址分配给指定的指针,该指针被声明为保存比x
少的字节数据类型的地址,则在使用间接运算符时会读取错误的字节数。