1

a = f;给定以下 C 代码,和有什么区别a = (int *) f;

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

6 回答 6

5
float *f;
int *a;

a = f;

这个赋值是错误的(存在 C 约束冲突),指针类型之间没有隐式转换(with 除外void *)。编译器可以拒绝编译带有这个赋值的程序。

于 2013-10-11T17:36:23.820 回答
4

鉴于:

float *f;
int *a;

这个:

a = f;

违反约束的。它需要来自任何符合要求的编译器的诊断。在发出所需的诊断后,它可能会或可能不会拒绝该程序。(恕我直言,它应该这样做。)符合标准的编译器可能会选择仅通过警告(这符合诊断条件)来接受它,但是一旦这样做,程序的行为就未定义。执行此操作的编译器通常会生成从float*to的隐式转换int*,提供与强制转换(显式转换)相同的行为,但标准并不要求这样做。

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

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

这个:

a = (int *) f;

获取f( 类型float*) 的值并将其显式转换为 type int*,然后将该int*值分配给a. (我假设声明和赋值之间的某些内容已设置f为某个有效值。)

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

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

这种转换,假设intfloat具有相同的大小并具有相似的对齐要求,可能旨在让您将float对象视为int对象。这称为“类型双关语”。如果大小不同int,或者它们float 不同的对齐要求,这很容易在您的脸上炸毁,使您的程序崩溃(如果您幸运的话)或给您垃圾结果(如果您不是)。(是的,使程序崩溃是一个好的结果;它让您知道存在问题。)

如果出于某种原因确实需要这样做,最好定义一个unionwithintfloat成员,或者用于将对象memcpy()的内容复制floatint对象中。

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

于 2013-10-11T18:35:22.840 回答
3

6.5.16.1 简单赋值

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

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

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

于 2013-10-11T17:29:21.447 回答
2

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

于 2013-10-11T17:43:17.350 回答
2

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

于 2013-10-11T17:29:20.583 回答
1
a = f; //assignment
// is a constraint violation

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

将浮点指针显式转换为 int 指针。简单地隐藏编译器警告或错误。但是在运行时很可能会崩溃,因为取消引用指针时程序所期望的大小与现实不同。

于 2013-10-11T17:37:46.303 回答