如果我用一个空参数表声明一个函数,然后传递参数怎么办?

时间:2016-02-16 07:25:39

标签: c parameters command-line-arguments declaration function-declaration

例如,

if(!function() { return false; }) {
    console.log("False");
} else {
    console.log("True");
}

输出:

#include <stdio.h>

void foo();

int main(void)
{
        foo();
        foo(42);
        foo("a string", 'C', 1.0);
        return 0;
}

void foo()
{
        puts("foo() is called");
}

此代码编译良好(没有使用clang的警告)并且运行良好。但我想知道传递给foo() is called foo() is called foo() is called 的值会发生什么变化?他们被推入堆栈还是被丢弃?

也许这个问题听起来毫无用处,但确实有道理。例如,当我有foo()而不是int main()并向其传递一些命令行参数时,int main(void)的行为是否会受到影响?

此外,使用main()时,ISO <stdarg.h>之前至少需要一个命名参数。我们是否可以使用...之类的声明来传递函数的零到无限参数?

我注意到void foo()是一个&#34;非原型声明&#34;并且void foo()是&#34;原型声明&#34;现在。这有点相关吗?

澄清

似乎这个问题被标记为What does an empty parameter list mean? [duplicate]的重复(有趣的是,这个问题也是重复的......)。事实上,我认为我的问题与那个问题无关。它侧重于&#34; C {#1}中的void foo(void)意味着什么,但我知道这意味着&#34;我可以将任意数量的参数传递给它&#34;,我也知道它&#39;这是一个过时的功能。

但这个问题完全不同。关键字是&#34;如果&#34;。我只是想知道我是否向void foo()传递了不同数量的参数,就像上面的示例代码一样,它们可以在void foo()中使用吗?如果是这样,这是怎么做到的?如果没有,传递的参数会有什么不同吗?这是我的问题。

2 个答案:

答案 0 :(得分:2)

在C中,void foo()声明一个带有未指定数量参数的函数。以下列方式声明function

return-type function-name(parameter-list,...) { body... }

parameter-list是函数以逗号分隔的参数列表。如果没有给出参数,那么该函数不带任何参数,应该用空的括号或用关键字void定义。如果参数列表中的变量前面没有变量类型,则假定为int。

答案 1 :(得分:1)

正如Jonathan Leffler所说,C的调用约定确定调用函数(不是被调用函数)负责从堆栈中弹出参数,因此即使参数与参数不匹配,程序也不会崩溃被称为函数期望。

我补充说C的调用约定也确定参数以相反的顺序被压入堆栈(即调用foo (1, 2)推送2然后{{1 }})。这允许被调用函数访问第一个参数,即使它不知道其余参数。例如,即使不知道已传递了哪些其他参数,声明为1的函数也能够访问int foo (int a, int b, ...)aba只是在堆栈顶部。访问其他参数需要堆栈指针黑客,这正是b所做的。当然,通过使用不同的参数(例如printf),可以轻松获得有趣的结果。

因此,根据问题,是的,printf ("%d%d", 3.5);可以使用任何数量/类型的参数安全地调用,并且在1980年代,它将被视为&#34;正常实践&#34;使用堆栈上的指针hacks来访问未知参数。当可移植性和可读性变得越来越受关注时,int foo ()作为实现这些指针攻击的可移植方式出现(编译器将为目标平台生成正确的代码,因此它不再是&#34;劈&#34)。但是,正如所述,<stdarg.h>至少需要一个参数,因此无法帮助<stdarg.h>