您需要更认真地对待编译器警告。
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 \n q = %f, p = %p, &q = %p \n",*p,q,p,&q);
%f
格式需要一个double
参数(在这种情况下,一个参数float
被提升为double
这样float
就可以了)。但*p
属于类型int
。printf
使用错误类型的参数调用会导致程序的行为未定义。
%p
需要 type 的参数void*
,而不仅仅是任何指针类型。如果要打印指针值,应将其转换为void*
:
printf("&q = %p\n", (void*)&q);
它可能在没有演员表的情况下工作,但同样,行为是未定义的。
如果您在编译程序时收到任何警告,请不要费心运行它。首先修复警告。
至于标题中的问题,类型指针和类型int*
不同float*
。Anint*
应该指向一个int
对象;afloat*
应该指向一个float
对象。您的编译器可能会让您混合使用它们,但这样做的结果是实现定义或未定义。C 语言,尤其是许多 C 编译器,会让你摆脱很多没有多大意义的事情。
它们是不同类型的原因是(试图)防止或至少检测它们使用中的错误。如果您声明一个类型为 的对象,int*
则表示您打算让它指向一个int
对象(如果它不是空指针)。float
在对象中存储对象的地址int*
几乎可以肯定是一个错误。强制类型安全允许尽早检测到此类错误(当您的编译器打印警告时,而不是当您的程序在一个重要客户端的演示期间崩溃时)。
很可能(但不能保证)int*
并且float*
大小相同并且具有相同的内部表示。但是对象的含义不是int*
“包含虚拟地址的 32(或 64)位的集合”,而是“指向int
对象的东西”。