声明不完整的 C 函数

C function with incomplete declaration

我可以使用 gcc -std=C99 -Wall:

构建这个示例而不会出错
void dummy() {}

int main(void) {
    dummy(1, 2, 3);
    dummy(120, 144);
}

反汇编表明该函数确实被调用了两次:

main:
.LFB1:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        movl    , %edx
        movl    , %esi
        movl    , %edi
        movl    [=11=], %eax
        call    foo
        movl    0, %esi
        movl    0, %edi
        movl    [=11=], %eax
        call    foo
        movl    [=11=], %eax
        popq    %rbp
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc

我承认这段代码不应该存在,但是它是允许的,我想知道它在哪种特殊情况下会有用。

有什么线索吗?

编辑

问题calling-c-functions-with-too-many-arguments没有回答这个问题。它提供了有关如何使用 varadic 的信息,但没有提供不完整声明可能有用的示例。

问题也没有回答问题。它解释了不完整原型和完整原型之间的区别,这不是我的问题。

所以,看来我的问题不够明确,我再举个例子:

假设我真的会利用不完整的声明来使用变量参数而不使用 varadic 方法,所以我将示例写为:

int main(void) {
    dummy(1, 2, 3);
    dummy(1, 2, 3, 4, 5, 6, 7, 8);
}

根据调用约定,第一个函数将使用CPU寄存器传递参数,而第二个调用将使用堆栈。

现在在我的 dummy 函数中,如何读取这些参数并知道是否使用了堆栈?

来自C11 standard 6.7.5.3p14

An empty list in a function declarator that is part of a definition of that function specifies that the function has no parameters.

void dummy() {} 是一个函数声明符,它是一个函数定义(它有 {} 函数体定义)。 dummy 函数有一个空的标识符列表 - 函数声明内的 ( ) 大括号内没有任何内容。这意味着该函数不带参数。

int main(void) {
    dummy(1, 2, 3);
    dummy(120, 144);
}

使用任何参数调用dummy都是无效的,因为参数与函数声明不匹配。这是未定义的行为。

Now in my dummy function, how can I read these arguments and know whether or not the stack was used?

你不能。除非你做一些 hardware/compiler 特定的 assembly/pointer 技巧。 C 标准不使用术语 "stack" 和堆栈的用法,如果它存在 and/or 则完全使用以及如何使用,这取决于体系结构和编译器。架构上可能不存在堆栈。要读取函数参数,您必须在函数定义内的参数列表中声明它们。