【问题标题】:When is function argument conversion done?函数参数转换何时完成?
【发布时间】:2013-07-11 21:37:02
【问题描述】:

假设我这样声明:

void foo(uint64_t);

并且这个函数是在一个外部汇编文件中定义的。现在我从 C 代码中这样称呼它:

uint32_t x = 42;
foo(x);

x 何时转换为 uint64_t?我是否可以依靠我的汇编代码在相关目标的 ABI 要求的任何寄存器/堆栈位置始终接收uint64_t,还是我必须自己进行转换?

换句话说,当函数定义对编译器不可用时,foo(x)foo((uint64_t)x) 是否等效?这可能是一个愚蠢的问题,但我不确定这里到底发生了什么。

【问题讨论】:

  • 我编辑了词汇表的标题。在 C 标准术语中,强制转换是一种“显式转换”。看来您只是在要求“隐式转换”。

标签: c arguments type-conversion


【解决方案1】:

在 c11 规范 6.5.2.2-4 中:

在准备调用函数时,会计算参数,并为每个参数分配相应参数的值。

所以x 被强制转换(提升?转换?)为uint64_t 在函数调用之前

【讨论】:

  • 不,它从来没有“铸造”过。它被提升了。
  • 事实上,它从来不是“演员”。 :)
  • @H2CO3 它是“转换的”,而不是“提升的”。
【解决方案2】:

您可以避免显式转换它,因为它会被提升uint64_t

编辑: @H2CO3 的answer 很好地解释了这件事。

【讨论】:

  • 函数参数发生的事情是conversion,而不是promotionvoid f(int x); f(1LL); 导致 1LL 转换为 int,但从 long long 转换为 int 几乎不是“促销”。
【解决方案3】:

显然,它从不 转换uint64_t,我没有看到该代码中发生任何类型转换。相反,它升级uint64_t,是的,它总是自动发生(根据“通常的算术转换”,正如标准的措辞)。因此,您无需手动投射。

换句话说,当函数定义对编译器不可用时,foo(x)foo((uint64_t)x) 是否等效?

如果只有定义不可用,它们就是这样。但是,如果 declaration 丢失,那就另当别论了...(您不应该这样做!-它将调用未定义的行为,因为 uint32_t 将被假定为参数的类型,但事实并非如此。)

【讨论】:

  • 是的,声明本身总是存在的——但是函数是用汇编编写的,所以编译器通常无法获得函数的定义。谢谢,这很有意义:)
  • @Thomas 不客气。声明总是足够的。 是声明的目的。 (如果编译器需要定义,那将是一团糟!)
  • 只是为了词汇,在C标准行话中这实际上不是“提升”而是“转换”。 “整数提升”是在范围内没有原型时有效的规则,窄类型被提升为 int 之类的东西。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-08-31
  • 2015-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多