【问题标题】:What is necessity of sign-extension? [closed]符号扩展的必要性是什么? [关闭]
【发布时间】:2025-11-24 16:20:07
【问题描述】:

考虑以下一段 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. 如果它降低了性能,我们应该怎么做才能提高它?

【问题讨论】:

  • 你在什么机器上编译代码?
  • 这个问题太笼统了。您基本上是在问,“计算机如何运行程序?”我不认为它真的适合这里。
  • @dan1111 这个问题是关于表达式中正常的charint 的提升。也许,表达不清。

标签: c performance optimization sign-extension


【解决方案1】:
  1. 这是谁做的? - 归根结底,是 CPU 做的;编译器生成所有相关指令供 CPU 执行转换
  2. 进行这么多转换的必要性是什么? - 这些转换对于确保跨多个 C 编译器支持的多个平台的结果保持一致是必要的。
  3. 会降低/提高机器/编译器的性能吗? - 与“什么都不做”相比,这会降低性能,但没有人会注意到差异。
  4. 如果它降低了性能,我们应该怎么做才能提高它? - 没有:如果您必须对chars 执行算术运算,那么您对chars 执行算术运算。让优化器负责为您的平台删除所有不必要的指令。在大多数情况下,CPU 的指令与 C 语言所需的语义兼容,因此生成的代码会很短。

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

【讨论】:

    【解决方案2】:

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

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

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

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

    【讨论】:

      【解决方案3】:
      1. 运行时的代码。编译器生成所需的代码来实现编程语言的指定语义。
      2. 我不确定您所说的推送到“堆栈”,据我所知,C 中没有这样的要求。
      3. 这没有意义;与什么相比?
      4. 您可以尝试删除无意义的c 变量,只保留return (char) (a + b);。也就是说,我认为这个函数没有太多需要“优化”的地方。它应该编译成很少的代码。如果你可以将它内联,它可能会是 1 条指令的顺序。

      【讨论】:

      • W.r.t #2。我认为 OP 正在谈论使用堆栈实现的抽象表达式评估机。实现(真实的,非抽象的)也可能是真正的堆栈机器。
      【解决方案4】:

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

      但是,为了回答您的模糊问题:

      1. 编译器执行此操作是为了响应您编写代码。谁编写代码?一个开发者,我想。 在你写问题的时候这样做了。
      2. 如果有必要(因为您没有引用您的来源),我想这是为了让 CPU 可以本地处理算术。
      3. 从技术上讲,它会减少它,但仅与具有任意位数的理论机器相比。实际上,这并没有明显的区别。
      4. 如果您使用与架构的本机位数相匹配的数据类型,性能会有非常轻微的提升。但是,这非常轻微,通常不值得带来不便。

      【讨论】:

      • OP 正在讨论表达式中小于int 的整数类型(例如charshort)到int 的正常转换。那是语言标准规定的行为。实际的转换是使用符号扩展实现的。
      • OP 专门讨论char;我的理解是char 至少 8位,但可能不是完全 8位,具体取决于实现。
      最近更新 更多