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

时间:2013-04-03 15:01:52

标签: c pointers

我尝试运行此代码,

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<stdio.h>
void main()
{   
    int *p;
    float q;
    q = 6.6;
    p = &q;
    printf("*p =  %f \n q = %f, p = %p, &q = %p \n",*p,q,p,&q);
}

3 个答案:

答案 0 :(得分:9)

您需要更严肃地对待编译器警告。

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需要类型void*的参数,而不仅仅是任何指针类型。如果要打印指针值,则应将其强制转换为void*

printf("&q = %p\n", (void*)&q);

没有强制转换可能会有效,但同样,行为未定义。

如果在编译程序时收到任何警告,请不要打扰它。首先修复警告。

至于标题中的问题,int*float*类型的指针属于不同类型。 int*应指向int个对象; float*应指向float对象。您的编译器可能会让您混合它们,但这样做的结果是实现定义或未定义。 C语言,特别是许多C编译器,可以让你逃避许多没有多大意义的事情。

它们是不同类型的原因是(尝试)防止或至少检测其使用中的错误。如果声明类型为int*的对象,则表示您打算将其指向int对象(如果它不是空指针)。在float对象中存储int*对象的地址几乎肯定是一个错误。强制类型安全性允许尽早检测到此类错误(当您的编译器打印警告时,而不是在重要客户端的演示过程中程序崩溃时)。

int*float*可能(但不能保证)具有相同的大小且具有相同的内部表示。但是int*对象的含义不是“包含虚拟地址的32(或64)位的集合”,而是“指向int对象的东西”

答案 1 :(得分:8)

您正在获取未定义的行为,因为您将错误的类型传递给printf。当你告诉它期望浮动时,它实际上需要一个double - 但是你传递int

因此它会输出错误的信息,因为printf完全依赖于格式字符串来访问您传递的参数。

答案 2 :(得分:0)

除了teppic所说的,

考虑,

int a = 5;
int *p = &a;

在这种情况下,我们向编译器指出p将指向一个整数。所以众所周知,当我们在运行时执行*p之类的操作时,不会。将读取等于int大小的字节数。

如果将一个占用x字节数的数据类型的地址分配给一个指针,该指针被声明为保存比x更少字节数据类型的地址,则读取错误的字节数使用间接运算符。