0

零.c:

    int sq();

一.c:

    int sq(int i) { return i*i; }

二.c:

    int sq(int i, int j);

主.c:

    int main() {
        printf("%d\n",sq());
        printf("%d\n",sq(2));
        printf("%d\n",sq(2,3));
    }

然后我单独编译每个文件并gcc zero.o one.o two.o main.o -o main

./main

1
4
4

我有点困惑这将如何成功。当我打电话sq()sq(2)sq(2,3)

4

4 回答 4

0

所以,我之前根据我在帖子中读到的内容写了一个答案。这是错误的。这是正确的答案。

zero.c 不生成任何代码。two.c 不生成任何代码。

main.c 和 one.c 是唯一实际生成代码的文件。

在 one.c 中使用一个参数调用一个sq(int i)没有参数的函数是未定义的行为(因此“任何事情都可能发生”,包括在某些情况下类似于您所期望的事情)。使用两个参数调用也是未定义的行为 - 同样,当你这样做时它不一定会“出错”,但你不能保证它工作(或做你期望的) - 例如它也可以返回 9 因为它将参数从最后一个到第一个放入寄存器。

于 2013-05-13T16:08:34.367 回答
0

如果您想知道真正发生了什么,请让 gcc 输出 main.o 的程序集并查看一下。我想你会发现,当你调用 sq() 时,参数被加载到你机器上的基址寄存器中,然后 sq(int i) 将在第一个寄存器上执行乘法指令。如果你传递额外的参数,它们不会有任何影响,如果你不传递任何参数,它只会对之前加载到该寄存器中的任何值起作用。

于 2013-05-13T16:04:22.357 回答
0

zero.c & two.c 没有任何函数定义。这只是原型声明。因此,它不会创建任何具有函数定义的汇编代码。gcc -s(提示:使用标志编译以进行验证。)

只有 two.c 有函数定义。因此 two.s 将有一个函数sq,它接受第一个参数(通常在堆栈或处理器的第一个寄存器上传递,如 intel 上的 eax 或 arm 中的 r0)并返回其平方。

由于您没有在 main.c 中给出任何原型,编译器 (.c -> .s) 不会抱怨。它可能会将视为int sq(...),但我不确定。

因此,对于 3 个不同的输入: sq(), sq(2),sq(2,3)都将调用同一个函数,该函数在 two.c 中声明。

现在,sq(2)&的输出sq(2,3)很明显 - 返回传递的第一个参数的平方。的输出sq()将取决于在 sq 的堆栈中看到的堆栈/eax/r0 上的内容。好像是1.提示:在gdb下运行验证。

于 2013-05-13T16:23:59.063 回答
0

According to the C spec, your code invokes undefined behavior in multiple ways (and possibly more):

  • Two declarations of the same function in the same scope use different return or argument types/counts
  • For a call to a function without a function prototype in scope, the number of arguments does not equal the number of parameters

Since this is undefined behavior, you have no way to predict what will happen. The result doesn't even necessarily have to be consistent. If you aren't seeing compile-time warnings/errors for this code, then you need to turn up your compiler's warning level.

Adding a prototype in main.c will probably resolve the compiler's warnings with this code. The linker may still have issues, though, because you have multiple functions with the same name in the same scope and it's not exactly clear which one you want the code to use.

于 2013-05-13T16:30:41.920 回答