Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/163.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C/C++;主要功能';s参数?_C++_C_Parameters_Location_Main - Fatal编程技术网

C++ C/C++;主要功能';s参数?

C++ C/C++;主要功能';s参数?,c++,c,parameters,location,main,C++,C,Parameters,Location,Main,在C/C++中,主函数接收char*类型的参数 int main(int argc, char* argv[]){ return 0; } argv是一个char*数组,指向字符串。这些绳子在哪里?它们是在堆上、堆栈上还是在其他地方?它们具有编译器的魔力,并且依赖于实现 虽然您可以访问实际参数,但我认为它们的实际位置根本不重要。参数列表是流程环境的一部分,类似于(但不同于)环境变量。这些参数与任何其他函数的参数没有区别。 如果体系结构的调用序列需要参数通过堆栈,则它们位于堆栈上。如果像on

在C/C++中,主函数接收
char*
类型的参数

int main(int argc, char* argv[]){
  return 0;
}

argv
是一个
char*
数组,指向字符串。这些绳子在哪里?它们是在堆上、堆栈上还是在其他地方?

它们具有编译器的魔力,并且依赖于实现

虽然您可以访问实际参数,但我认为它们的实际位置根本不重要。

参数列表是流程环境的一部分,类似于(但不同于)环境变量。

这些参数与任何其他函数的参数没有区别。
如果体系结构的调用序列需要参数通过堆栈,则它们位于堆栈上。如果像on一样,x86-64某些参数进入寄存器,这些参数也会进入寄存器。

通常不知道它们在哪里

#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[]) {
  char **foo;
  char *bar[] = {"foo", "bar"};

  (void)argv; /* avoid unused argv warning */

  foo = malloc(sizeof *foo);
  foo[0] = malloc(42);
  strcpy(foo[0], "forty two");

  /* where is foo located? stack? heap? somewhere else? */
  if (argc != 42) main(42, foo); else return 0;

  /* where is bar located? stack? heap? somewhere else? */
  if (argc != 43) main(43, bar); else return 0;
  /* except for the fact that bar elements
  ** point to unmodifiable strings
  ** this call to main is perfectably reasonable */

  return 0;
  /* please ignore memory leaks, thank you */
}
#包括
#包括
int main(int argc,char*argv[]){
char**foo;
char*bar[]={“foo”,“bar”};
(void)argv;/*避免未使用的argv警告*/
foo=malloc(sizeof*foo);
foo[0]=malloc(42);
strcpy(foo[0],“四十二”);
/*foo在哪里?堆栈?堆?其他地方*/
如果(argc!=42)main(42,foo);否则返回0;
/*酒吧在哪里?堆垛?堆?其他地方*/
如果(argc!=43)main(43,bar);否则返回0;
/*除了bar元素
**指向不可修改的字符串
**这个对main的调用非常合理*/
返回0;
/*请忽略内存泄漏,谢谢*/
}

这个问题的答案取决于编译器。这意味着它不在C标准中处理,因此任何人都可以按照自己的意愿实现它。这是正常的,因为操作系统也没有一个通用的、被接受的、标准的方法来启动和完成进程

让我们想象一个简单的,为什么不呢

进程通过某种机制接收命令行中写入的参数。argc只是一个int,编译器将引导函数作为程序进程(运行时的一部分)的入口点推送到堆栈中。实际值是从操作系统获取的,可以写入堆的内存块中。然后构建argv向量,并将其第一个位置的地址推入堆栈


然后调用必须由程序员提供的函数main(),并保存其返回值以供以后(几乎中间)使用。堆中的结构被释放,为main获得的退出代码被导出到操作系统。进程结束。

正如
pmg
所提到的,当递归调用
main
时,参数指向的位置取决于调用方。在最初调用
main
时,答案基本相同,只是“调用者”是C实现/OS


在UNIX-y系统上,
argv
指向的字符串、
argv
指针本身以及进程的初始环境变量几乎总是存储在堆栈的最顶端。

它实际上是编译器依赖性和操作系统依赖性的组合
main()
与任何其他C函数一样,是一个函数,因此两个参数
argc
argv
的位置将遵循平台上编译器的标准。e、 g.对于大多数以x86为目标的C编译器,它们将位于返回地址和保存的基指针上方的堆栈上(记住,堆栈向下增长)。在x86_64上,参数在寄存器中传递,因此
argc
将位于
%edi
中,
argv
将位于
%rsi
中。编译器生成的主函数中的代码然后将它们复制到堆栈中,这就是后面引用的位置。这样寄存器就可以用于
main
的函数调用


argv指向的
char*
s块以及实际的字符序列可以在任何地方。它们将从某个操作系统定义的位置开始,并可能被链接器生成的预编译代码复制到堆栈或其他地方。您必须查看
exec()
的代码和链接器生成的汇编程序预编译,才能找到答案。

以下是C标准()的说明:

5.1.2.2.1程序启动

2如果已声明,则主功能的参数应符合以下要求 约束条件:

  • argc的值应为非负。

  • argv[argc]应为空指针。

  • 如果argc的值大于零,则数组成员argv[0]到 argv[argc-1]应包含指向给定字符串的指针 程序启动前主机环境定义的实现值。这个 目的是向程序提供程序启动前确定的信息 来自托管环境中的其他位置。如果主机环境无法 为字符串提供大写和小写字母,实现 应确保以小写形式接收字符串。

  • 如果argc的值大于零,则argv[0]指向的字符串 表示程序名;如果 程序名在主机环境中不可用。如果argc的值为 大于1时,argv[1]通过argv[argc-1]指向的字符串 表示程序参数。

  • 参数argc和argv以及argv数组指向的字符串应 可由程序修改,并在程序之间保留其最后存储的值 启动和程序终止。
最后一个项目符号是存储字符串值的最有趣的wrt。它没有指定堆或堆栈,但它确实要求字符串是可写的,并且具有静态范围,这对字符串内容的位置设置了一些限制。像其他人一样