2

考虑以下一段 C 代码 -

char sum_char(char a,char b)
{
   char c = a+b;
   return c;
}

它涉及 -

  1. 将第二个参数转换为符号扩展。
  2. 将签名的扩展参数作为 b 推送到堆栈上。
  3. 将第一个参数转换为符号扩展。
  4. 将签名的扩展参数作为 a 推送到堆栈上。
  5. 添加 a & b,将结果转换为 char 并将其存储在 c 中。
  6. C 再次符号扩展。
  7. 符号扩展 c 被复制到返回值寄存器和函数返回给调用者。
  8. 要存储结果调用函数再次将 int 转换为 char。

我的问题是——

  1. 这是谁做的?
  2. 做这么多转换的必要性是什么?
  3. 它会降低/提高机器/编译器的性能吗?
  4. 如果它正在降低性能,我们应该怎么做才能提高它?
4

4 回答 4

2

您描述的转换仅在抽象机器中执行。如果它导致相同的可观察行为,编译器可以简化所有这些。

打开优化时,我的编译器将其转换为以下汇编器

sum_char:
.LFB0:
    .cfi_startproc
    leal    (%rsi,%rdi), %eax
    ret
    .cfi_endproc
.LFE0:
    .size   sum_char, .-sum_char

这只是一个加法(隐藏在leal指令中)和一个ret跳转。

于 2012-10-02T14:28:44.237 回答
2
  1. 这是谁做的?- 最终,是 CPU 执行此操作;编译器为 CPU 生成所有相关指令以执行转换
  2. 做这么多转换的必要性是什么?- 必须进行转换以确保跨多个 C 编译器支持的多个平台的结果的一致性。
  3. 它会降低/提高机器/编译器的性能吗?- 与“什么都不做”相比,这会降低性能,但没有人会注意到差异。
  4. 如果它正在降低性能,我们应该怎么做才能提高它?- 无:如果必须对 s 执行算术运算char,则对 s 执行算术运算char。让优化器负责为您的平台删除所有不必要的指令。在大多数情况下,CPU 都有与 C 语言所需语义兼容的指令,因此生成的代码会很短。

当然如果不需要对有符号字符进行操作,也可以对无符号字符进行操作。这消除了很多符号扩展。

于 2012-10-02T14:32:45.663 回答
1
  1. 代码,运行时。编译器生成所需的代码以实现编程语言的指定语义。
  2. 我不确定你所说的推动“堆栈”,据我所知,C 中没有这样的要求。
  3. 那没有意义;相比什么?
  4. 您可以尝试删除无意义的c变量,然后将return (char) (a + b);. 也就是说,我认为这个函数没有太多需要“优化”的地方。它应该编译成很少的代码。如果您可以将其内联,则它可能是 1 条指令的顺序。
于 2012-10-02T14:28:27.590 回答
0

我不确定你的问题的细节。您反复引用符号扩展而不引用任何来源;我猜你假设char数据类型将被扩展以匹配 CPU 的位数,但我认为不能保证情况并非如此。

但是,作为回答您模糊问题的尝试:

  1. 编译器这样做是为了响应您编写代码。谁编写代码?一个开发者,我想。 当你写这个问题时,你这样做了
  2. 如果有必要(因为你没有引用你的来源),我想这是为了让 CPU 可以本地处理算术。
  3. 从技术上讲,它会减少它,但仅与具有任意位数的理论机器相比。实际上,它没有明显的区别。
  4. 如果您使用与体系结构的本机位数相匹配的数据类型,则会有非常轻微的性能提升。然而,这是非常轻微的,通常不值得带来不便。
于 2012-10-02T14:33:22.723 回答