首页 > 解决方案 > printf 如何转换传入的参数?

问题描述

我有以下添加函数的实现:

int add(int a, int b) {
    return a + b;
}
unsigned add(unsigned a, int b) {
    return a+b;
}
char* add(char* a, int b) {
    return &a[b];
}
const unsigned char add[6] = {0x8d, 0x04, 0x37, 0xc3};

这是调用它的文件

#include <cstdio>
#include <cstdlib>

extern "C" {
   int add(int a, int b);
}

int main(int argc, char* argv[]) {
    if (argc <= 2) {
        fprintf(stderr, "Usage: add A B\n\
    Prints A + B.\n");
        exit(1);
    }

    int a = strtol(argv[1], 0, 0);
    int b = strtol(argv[2], 0, 0);
    printf("%d + %d = %d\n", a, b, add(a, b));
}

事实证明,添加函数的所有实现都会产生相同的结果,无论 a、b 值如何(正数、负数)。怎么可能?我认为魔法发生在 printf 函数中,但我不确定。我从这里获取源代码https://github.com/cs61/cs61-lectures/tree/main/datarep1

标签: c++printf

解决方案


怎么可能?

为您的目标机器生成的机器代码,我猜是 x86 的 32 位版本,因为add编译源文件的每种情况的符号在每种情况下都是相同的,并且在每种情况下都是相同的。因此,当使用每个符号执行代码时,函数的作用相同 - 添加两个数字。

请注意,编写函数参数类型或函数返回类型不“匹配”的代码是一个非常严重的错误。

const unsigned char add[6] = {0x8d, 0x04, 0x37, 0xc3};

这些是以原始字节编码的程序集。这个网站https://defuse.ca/online-x86-assembler.htm#disassembly2告诉我:

0:  8d 04 37                lea    eax,[edi+esi*1]
3:  c3                      ret

它是lea带有 a 的指令ret,有效地添加了参数。


推荐阅读