繁体   English   中英

何时强制类型转换指针?

[英]When is typecasting a pointer allowed?

我正在为考试而学习,下面给出的示例问题之一是:

“当分配给new_val时,以下哪个表达式(该表达式将替换HERE )将输出7 选择所有适用项:

float m = 7.0
int *a = (int *) &m;

int new_val = HERE;
printf("%d\n", new_val);

(a)*(int *)&m

(b)* a

(c)(整数)米

(d)以上都不是。


答案仅是(c)

我已经在自己的机器上运行了该程序,发现符合答案。 但是,我想知道有人怎么能找到这个答案? 更一般而言,我在理解有关强制转换指针的规则时遇到了麻烦。 我已经阅读了StackOverflow上的其他几篇文章,对我来说并没有太大帮助。

我想知道是否有人可以帮助澄清我如何解决与此类似的问题。

但是使用

int new_val = (int)m;

使用int* a = ...忽略在上一行中完成的所有操作

因此,您只是将原始浮点数m投射回一个int。

编辑尝试以下操作:


#include "stdio.h"

int main(int argc, char** argv) {
    float m = 7.1;
    int new_val = (int)m;
    printf("%d\n", new_val);

}

解决此问题的方法是查看每个选择答案,然后弄清该语句的含义。 考虑变量的类型。

但是,在这种情况下,将float *强制转换为int *只是意味着您要告诉编译器“您知道该存储有float内存地址?像访问int一样访问该内存”。 intfloat不会以相同的方式存储在内存中,因此尝试以错误的格式访问它会产生无意义的结果。 强制转换指针不会转换指针指向的数据。

对于选项c,请注意,您没有强制转换指针,而是将float转换为int 这是一个简单的转换。

这个问题是有缺陷的。 C标准允许(a),(b)和(c)中的每一个都打印“ 7”,并且还允许它们中的每一个都不打印“ 7”。

对于(a),我们有int new_val = * (int *) &m; 在这里, &m类型为float * ,因此将float *转换为int * C 2018 6.3.2.3 7告诉我们我们可以进行这种转换:“指向对象类型的指针可能会转换为指向不同对象类型的指针。”但也“如果生成的指针未针对引用类型正确对齐,因此,在float的对齐要求比int严格的实现中,该行为不是由C标准定义的,因此,合格的C实现允许打印“ 7”,并且不允许打印“7”。 假设实现成功评估了转换而没有对齐问题,则应用* 下一节将对此进行介绍。

在(b)中,我们有int new_val = *a; ,其中a已初始化为(int *) &m; 与(a)一样,此表达式将float *转换为int * ,因此不符合上面的对齐问题。 但是,再次假设避免了对齐问题,它随后使用指针访问float对象m ,就好像它是一个int 这违反了C 2018 6.5 7,其中声明“对象只能通过具有以下类型之一的左值表达式访问其存储的值:”然后继续列出各种选项,这些选项均不允许以以下方式访问float :一个int 由于违反了此“应有”要求,C 2018 4 1告诉我们该行为未定义:“如果违反了在约束或运行时约束之外出现的“应有”或“不应”要求,则该行为未定义。 ”由于C标准未定义行为,因此允许的符合性实现允许打印“ 7”,而不允许打印“ 7”。

在(c)中,我们有int new_val = (int) m; ,其中m是值为7的float 。这是定义明确的转换,结果为7,因此printf("%d\\n", new_val); 通常会打印“ 7”(带有换行符)。 但是,更早的问题仍然存在:即使使用new_val正确定义,更早的声明int *a = (int *) &m; 执行可能导致未定义行为的转换。 在我们阅读new_val的定义之前,这可能导致未定义的行为。 因此,与(a)和(b)一样,一致的实现方式允许打印“ 7”,而不允许打印“ 7”。

因为a = (int *)&m ,所以选项(a)和(b)相同。 在两种情况下,您都使用m的地址,将其强制转换为int * ,然后取消引用。

(a)和(b)不起作用的原因是&m是指向floatfloat * )的指针,而不是指向intint * )的指针。

考虑两个指针,一个是指向Window的指针,另一个是指向Joystick的指针。 很明显,您不能将它们混在一起,对吗? 您不能将指向Window的指针传递给需要指向Joystick的指针的函数。 您可以投射指针,但这不会使Window变成Joystick

因此,指向float指针与指向int指针是不兼容的,并且如果将指针转换为float并指向int的指针并尝试对其进行取消引用,则将得到垃圾。

但是(c)之所以有效,是因为这里要获取实际的floatm并要求编译器将该值转换为int值。 编译器知道如何执行此操作并生成正确的代码。

您可能想知道,如果编译器知道如何将float转换为int ,为什么不能将float的指针转换为int的指针呢? 实际上确实如此; 那是演员的目的。 但是它会转换指针,而不是指针指向的对象

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM