float指针和int指针地址有什么区别?

我试着运行这段代码,

int *p; float q; q = 6.6; p = &q; 

虽然这将是一个警告,但我认为&qp具有相同的大小,所以p可以具有q的地址。 但是当我打印&qp我得到不同的输出。 这是我的输出

 *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少的字节数据类型的地址,则在使用间接运算符时会读取错误的字节数。