c编程:类型转换有什么区别?

时间:2013-10-11 17:27:42

标签: c

鉴于以下C代码,a = f;a = (int *) f;之间有什么区别?

float *f;
int *a;
...
a = f;
a = (int *) f;

6 个答案:

答案 0 :(得分:5)

float *f;
int *a;

a = f;

此赋值是错误的(存在C约束违规),指针类型之间没有隐式转换(void *除外)。编译器可以拒绝使用此分配编译程序。

答案 1 :(得分:4)

假设:

float *f;
int *a;

此:

a = f;

约束违规。它需要来自任何符合标准的编译器的诊断。在发出所需的诊断后,它可能会也可能不会拒绝该程序。 (恕我直言,它应该这样做。)符合标准的编译器可以选择接受它只是一个警告(有资格作为诊断),但一旦它这样做,程序的行为是不确定的。执行此操作的编译器最常生成从float*int*的隐式转换,提供与存在转换(显式转换)相同的行为,但标准不需要。

不合格的编译器当然可以自由地做任何他们喜欢的事情。

结论:不要写那样的代码。即使你的编译器让你逃脱它,另一个编译器可能不会。如果要从一种指针类型转换为另一种指针类型,请使用强制转换。除了有效性问题之外,演员还会让读者更加清楚一些有趣的事情。如果你的编译器给你一个警告,请注意它。如果没有,请找出如何提高编译器的警告级别。

此:

a = (int *) f;

获取f(类型为float*)的值,并明确转换为<{1}},然后指定int*价值为int*。 (我假设声明和赋值之间的某些内容已将a设置为某个有效值。)

如果f是空指针,则转换定义良好,并产生类型为f的空指针。将非空对象指针转换为另一种指针类型的规则是(引用N1570 6.3.2.3p7):

  

指向对象类型的指针可以转换为指向a的指针   不同的对象类型。如果结果指针不正确   对于引用的类型,行为是未定义的。   否则,当再次转换回来时,结果应该相等   到原始指针。

这种转换,假设int*int大小相同且具有相似的对齐要求,可能会让您将float对象视为float对象{1}}对象。这被称为“打字”。如果intint 不是相同的尺寸,或者如果它们具有不同的对齐要求,那么这很容易在您面前爆炸,导致程序崩溃(如果您'很幸运)或给你垃圾结果(如果你不是)。 (是的,崩溃程序是良好的结果;它会让你知道有问题。)

如果您出于某种原因确实需要这样做,最好定义float unionint成员,或使用float复制内容将memcpy()个对象放入float对象中。

但做这种事情很少有意义。如果要检查int对象的表示形式,最好将其视为语言标准明确允许的float数组。

答案 2 :(得分:3)

6.5.16.1简单分配

  

左操作数具有原子,限定或非限定指针类型,并且(考虑到   两个操作数都是左值操作数在左值转换后的类型   指向兼容类型的限定或非限定版本以及指向的类型的指针   左边的所有限定符都是右边所指的类型。

因此,a = f是违反约束并调用未定义的行为。

在第二种情况下,您将f(通过强制转换)与兼容转换为a的类型。在C中进行投射是合法的(不确定其他语言)     但是应该注意的是,在投射f之后,仍然指向float,并且每当您将其指定给a时都必须投射它。

答案 3 :(得分:2)

a = (int*) f;明确表示您要将float*指针强制转换为int*指针。没有它,您将收到不兼容的指针类型错误。

答案 4 :(得分:2)

您的代码将编译(至少在我的linux和gcc中)。但是你会收到警告。 如果使用a = f;然后在代码中的某处使用a,则会得到错误的数据,因为浮点数以不同的格式存储在内存中。即使您先进行投射,也可能会得到错误的结果,但编译器会看到您的投射,并假设您知道自己在做什么。

答案 5 :(得分:1)

a = f; //assignment
// is a constraint violation

a = (int *) f; //cast + assignment

显式地将浮点指针强制转换为int pointer.simply隐藏编译器警告或错误。 但是在运行时可能会崩溃,因为当解除引用指针时程序所期望的大小与现实不同。