【问题标题】:Compile-time and run-time costs of implicit float conversions隐式浮点转换的编译时和运行时成本
【发布时间】:2014-03-27 08:04:06
【问题描述】:

假设我有以下 C 结构:

typedef struct {
    float a, b;
} Floats;

然后我有一个函数将创建这个结构的实例:

Floats createFloats(float aVal, float bVal) {
    Floats f = {aVal, bVal};
    return f;
}

现在基本上有 4 种可能的(句法)方式来创建相同的结构:

Floats f1 = createFloats(0.0f, 1.0f);             // (A) [Canonical?]
Floats f2 = createFloats(0.0, 1.0);               // (B)
Floats f3 = createFloats(0, 1);                   // (C)
Floats f4 = createFloats(((float)0), ((float)1)); // (D)

我的问题是,以上 4 种创建结构的方法在编译时和运行时有什么区别?具体来说,什么时候发生隐式浮点转换(比如 clang 和 gcc)。有人建议我不要使用(C)(而(D) 似乎有点过头了),但是如果转换发生在编译时,那么上述任何方法之间肯定没有区别吗?

【问题讨论】:

  • 在 A 到 C 的情况下没有运行时转换,这一切都是在编译时完成的(就像情况 D 一样)。但是如果你真的想知道,检查生成的代码,这是唯一的知道的方法。
  • 那么,程序集告诉你什么?
  • 编译器不会隐式计算函数的返回值,除非你指定constexpr

标签: c gcc clang implicit-conversion


【解决方案1】:

你可以很简单地检查这些事情。将您的示例编译成带有调试信息的目标文件,然后运行 ​​objdump 对其进行反汇编并显示该程序集以及 C 源代码:

cc -g -c example.c
objdump -dS example.o

这样做会为您的示例表明,即使没有优化,每个变体也会产生完全相同的汇编代码。

【讨论】:

  • 实际上,有一个-S标志在程序集生成阶段之后停止编译器(至少是gcc和clang),将程序集写入输出(文本)文件。还有 -fverbose-asm 在生成的程序集中引入一些 cmets。
  • 除非你没有原型,在这种情况下你会得到未定义的行为,但在情况 3 中可能会出现不同的未定义行为。
猜你喜欢
  • 1970-01-01
  • 2011-05-28
  • 1970-01-01
  • 2016-03-22
  • 2023-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多