rem*_*inn 58 c c++ parameters location program-entry-point
在C/C++中,main函数接收类型的参数char*.
int main(int argc, char* argv[]){
return 0;
}
Run Code Online (Sandbox Code Playgroud)
argv是一个数组char*,并指向字符串.这些字符串在哪里?它们是堆,堆栈还是其他地方?
Stu*_*Stu 31
它们是编译器魔术,并且依赖于实现.
Joh*_*ode 28
这是C标准(n1256)所说的:
5.1.2.2.1程序启动
...
2如果声明它们,主函数的参数应遵守以下约束:
- argc的值应为非负值.
- argv [argc]应为空指针.
- 如果argc的值大于零,则数组成员argv [0]到 argv [argc-1]包含指向字符串的指针,在程序启动之前由主机环境给出实现定义的值.目的是在程序启动之前从托管环境中的其他地方向程序提供信息.如果主机环境不能提供大写和小写字母的字符串,则实现应确保以小写形式接收字符串.
- 如果argc的值大于零,则argv [0]指向的字符串 表示程序名称 ; 如果程序名不能从主机环境获得,则argv [0] [0]应为空字符.如果argc的值大于1,则argv [1]通过argv [argc-1]指向的字符串 表示程序参数.
- 参数argc和argv以及argv数组指向的字符串应该可由程序修改,并在程序启动和程序终止之间保留它们最后存储的值.
最后一个项目符号是存储字符串值的最有趣的文件.它没有指定堆或堆栈,但它确实要求字符串是可写的并且具有静态范围,这对字符串内容可能位于何处设置了一些限制.正如其他人所说,具体细节将取决于实施情况.
Jer*_*myP 17
它实际上是编译器依赖和操作系统依赖的组合. main()是一个函数,就像任何其他C函数,所以这两个参数的位置argc和argv将遵循平台上的编译器的标准.例如,对于大多数针对x86的C编译器,它们将位于返回地址上方的堆栈上以及保存的基指针(堆栈向下增长,请记住).在x86_64上,参数在寄存器中传递,因此argc将进入%edi和argv将进入%rsi.编译器生成的main函数中的代码然后将它们复制到堆栈中,这是后面引用指向的位置.这样寄存器就可以用于函数调用main.
char*argv指向的块和实际的字符序列可以在任何地方.它们将在某个操作系统定义的位置启动,并且可以通过链接器生成到堆栈或其他位置的前导码复制.您将不得不查看exec()链接器生成的代码和汇编器前导码以查找.
这个问题的答案是编译器依赖的.这意味着它不符合C标准,因此任何人都可以按照自己的意愿实施.这是正常的,因为操作系统也没有通用的标准方法来启动进程并完成它们.
让我们想象一个简单的,为什么不是场景.
该进程通过某种机制接收在命令行中写入的参数.然后argc只是一个int,它被编译器放入的引导函数推送到堆栈,作为程序进程的入口点(运行时的一部分).实际值是从操作系统获得的,并且可以写在堆的内存块中.然后构建argv向量,并将其第一个位置的地址也推入堆栈.
然后调用必须由程序员提供的函数main(),并保存其返回值以供稍后(几乎中间)使用.释放堆中的结构,并将为main获取的退出代码导出到操作系统.该过程结束.