c++ - 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
解决方案
怎么可能?
为您的目标机器生成的机器代码,我猜是 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
,有效地添加了参数。
推荐阅读
- f# - 如何在 F# 中使用 nUnit 捕获失败?
- spring-boot - Spring Boot,Swagger - 无法呈现此定义
- c# - 如何在列表中找到相同的变量,然后检查它是哪个索引(c#)
- python - 如何在需要使用“fsolve”的函数中获取中间变量的值?
- python - 使用 asyncio 在 Python 中流式传输字典列表
- isabelle - 在 Isabelle 中,如何以其他格式(如 S-expression、Json 格式...)打印状态(即要证明的子目标)?
- ruby-on-rails - FrozenStringLiteralComment 的 Rubocop 自动更正不起作用
- node.js - 无法读取sails Js Mongo DB中未定义的属性'columnName'
- pandas - 为什么 df.interpotale() 在我的 python3 中不起作用?为什么它返回完全相同的数据帧而没有任何插值?
- r - 我该如何解决这个 R 问题依赖 'animation' 不适用于包 'gganimate'