C中非标准主类型签名的使用

时间:2013-06-02 22:17:15

标签: c main type-signature

正在浏览this site上提供的sudo的源代码,并遇到了这个超级奇怪的类型签名(Bonus问题:对于“类型签名”,是否有更像C的术语?)for main:< / p>

int
main(argc, argv, envp)
    int argc;
    char **argv;
    char **envp;
{

据我所知,风格本身就是oldskool K&amp; R.我真正感兴趣的是,主要是奖金论点,char **envp。为什么? sudo是一个相当标准的命令行工具,可以这样调用。当操作系统遇到未使用通常(int argc, char *argv[])?

定义的主要功能时,操作系统如何知道该怎么做

很多时候,我自己一直懒惰,完全放弃了论点,无论我写的任何程序看起来都运行得很好(C可能会发生最危险的事情,我知道:p)

我的问题的另一部分是,所有这些让你做的很酷的东西?我有一种预感它可以帮助堆积嵌入式编程,但我很遗憾地接触到了这种情况,并且无法真正说出来。 我很想看到一些具体的例子

2 个答案:

答案 0 :(得分:1)

http://en.wikipedia.org/wiki/Main_function

从第一段开始:

  

C和C ++标准也允许其他依赖于平台的格式,除了在C ++中返回类型必须始终为int; [3]例如,Unix(尽管不是POSIX.1)和Microsoft Windows有第三种格式给出程序环境的参数,否则可以通过stdlib.h中的getenv访问:

Google是你的朋友。此外,在这种情况下,操作系统不需要知道关于main的任何内容 - 它是编译器完成工作,只要它是编译器接受的有效参数,就没有问题。

答案 1 :(得分:1)

它只是指向环境的指针,与

相同
extern char **environ;

自版本7以来,两者都在unix中可用(版本6中没有环境变量)。名为extern的{​​{1}}已标准化; environ的第三个参数没有。除了某种时尚陈述外,没有理由使用3-arg main

调用main的进程设置代码不需要知道main是否需要3个参数,因为在带有2个参数的函数和带有3个参数的函数之间的汇编级别没有区别但是没有不要使用第三个。或者在不带参数的函数和带有2个参数且不使用它们的函数之间,这就是为什么main也可以工作的原因。

具有非类似unix的ABI的系统可能需要知道他们正在调用哪种int main(void)

将其放在一个文件中:

main

这是另一个:

#include <stdio.h>

int foo(int argc, char **argv)
{
  int i;
  for(i=0;i<argc;++i)
    puts(argv[i]);
  return 0;
}

从跨平台的语言 - 律师角度来看,这是完全错误的。我们向编译器撒谎了extern int foo(int argc, char **argv, char **envp); int main(int argc, char **argv) { char *foo_args[] = { "foo", "arg", "another arg" }; char *foo_env[] = { "VAR=val", "VAR2=val2" }; foo(3, foo_args, foo_env); return 0; } 的类型,并传递了比它想要的更多的参数。但在unix中,它可行。额外的参数只是无害地占用堆栈上的一个槽,在函数返回后由调用者正确地计算和清理,或者临时存在于被调用者不期望特别找到任何内容的寄存器中,以及调用者期望被调用者破坏,所以它不介意寄存器是否被重用于被调用者的其他目的。

这正是具有2-arg main的普通C程序中foo所发生的情况。在envp的程序中argcargv会发生什么。

但就像int main(void)本身一样,没有充分的理由在严肃的代码中利用这一点。类型检查对你有好处,并且知道你可以逃避它,应该知道你不应该