【问题标题】:passing more than required arguments to c function将超过所需的参数传递给 c 函数
【发布时间】:2013-06-14 08:58:12
【问题描述】:

如果我向函数传递的参数多于所需的参数,会发生什么?我预计被调用函数中的某些内容会损坏,但在一些小测试代码中一切正常。

例如:

void print()
{
    int x=10;
    printf("%d\n",x);
}
void main()
{
    print(0,0,0,0,0);
}

【问题讨论】:

  • 也许这回答了你想要的:stackoverflow.com/questions/51032/…
  • 作为一种习惯,在 C 中从不使用 () 声明或定义函数。对于空参数列表,始终使用 (void)。然后你善良的编译器会急切地向你解释你做错了什么。
  • Also C11 6.11“未来语言方向”将此标记为过时的行为,可能无法在 C 标准的未来版本中编译。 "The use of function declarators with empty parentheses (not prototype-format parameter type declarators) is an obsolescent feature."
  • @JensGustedt 啊!好点子。但是,当我使用图书馆时,这并不适用。基本上,如果 print 是作为没有头文件的 .o 提供的,那么我仍然可以使用许多参数调用 print 并链接它。
  • @vpillai,在任何给定架构上具体发生的情况取决于该架构使用的调用约定。例如,有些可能会将所有参数放在堆栈上,有些则具有第一个参数(如果类型足够)可以将它们传递到硬件寄存器中。在这两种情况下,您都可能会遇到麻烦,因为一端可能会访问另一端没有预料到的东西。还要记住,如果不知道原型,所有“窄”类型的参数都会扩展为int,所以可能会发生非常奇怪的事情。

标签: c compilation callstack function-calls


【解决方案1】:

这是未定义的行为。

(C99, 6.5.2.2p6) "如果表示被调用函数的表达式的类型不包含 原型,[...]如果参数的数量不等于数量 参数,行为未定义。"

我们从 6.9.1p7 知道 print 函数不提供原型。

C99, 6.9.1p7) “如果声明符包含参数类型列表,则 list 还指定了所有参数的类型;这样的声明者 还用作稍后调用同一函数的函数原型 在同一个翻译单元。如果声明符包含标识符 list,142) 参数的类型应在 以下声明列表。”

由于没有违反约束,因此不需要诊断消息。

【讨论】:

  • 好的。但是,知道我通过的所有零都会放在哪里吗? (也许,一个特定于 GCC 的答案)
  • @vpillai undefined 未定义,但带有 gcc 的程序集转储显示它们已被推入堆栈。
  • 其实我的疑惑来自于此。不会覆盖print的局部变量吗?
  • @vpillai 再次 undefined 是未定义的,你不应该这样做,它可以覆盖任何东西。
  • @ouah 参数所在的位置取决于 ABI。在我的 x86_64 上,它们在寄存器中传递。
【解决方案2】:

在函数调用中,编译器将决定是否将参数放入 CPU 寄存器中,否则,参数将进入堆栈内存 (http://www.technochakra.com/wp-content/uploads/assembly_stack.jpg)。

当您添加不存在的参数时,可能会导致未定义的行为,因为调用的函数代码可能未对齐堆栈内存访问。换句话说,调用代码将在函数内部以与预期布局不同的布局写入堆栈。

【讨论】:

    【解决方案3】:

    会遇到编译错误。 我在visual c++ 6.0中编译代码,编译输出:

    error C2660: 'print' : function does not take 5 parameters
    

    【讨论】:

    • 但在 GCC 中,只有当我有函数原型时才会发生编译错误。
    • 这无关紧要。首先:您正在使用 C++ 编译器进行编译。第二:所述编译器因其非常差的 C 标准合规性而臭名昭著。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-12
    • 1970-01-01
    相关资源
    最近更新 更多