再度认识main函数
一个老式的什么也不做的main函数如下:
void main() {}
现代标准下,main()函数返回一个int值,指示了程序的最终运行状态;通常使用return 0;表示程序运行期间没有发生错误。
int main() { return 0; }
这个返回语句可以省略,这等同于return 0;
int main() {}
当然,你也可以返回其它值,如return 1; 或 return -3...,可能代表程序在运行过程中发生了一些可能的情况。
main()函数的参数
main函数可以有两个输入参数:
- argc:指明参数的个数(即argv数组元素的个数)
- argv:以字符串数组表示的具体参数(一个包含多个字符串的数组)
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("argc: %d\n", argc);
printf("argv[0]: %s\n", argv[0]);
printf("argv[1]: %s\n", argv[1]);
}

默认情况下,argc总是1,argv[0]则是当前应用程序的名称。这里有两点要思考:
- argc指示数组只有1个元素, 但当我们越界访问argv[1]时,输出是(null)而非垃圾值。
- argv数组的每个元素类型是char*而非const char*,即这些元素是可写的。
据此我们可以假想main函数被调用的过程如下:
// 构建参数数组(为了方便,我们这里假设一个参数最大长度为128字符)
char argv[][128] =
{
"C:\\zyf\\tutorial.exe", // argv[0] --> char[128]
NULL // argv[1] --> char[128]
};
// 计算参数个数(NULL不是有效的参数需要减1)
int argc = sizeof(argv) / sizeof(argv[0]) - 1;
// 操作系统调用main函数
return main(argc, argv)
一个完整的示例如下:
#include <stdio.h>
void my_main(int argc, char *argv[])
{
for (int i = 0; i < argc + 1; i++)
{
printf("argv[%d]: %s\n", i, argv[i]);
}
}
int main()
{
// 构建参数数组
char path[] = "C:\\zyf\\tutorial.exe";
char *argv[] = { path, NULL };
// 计算参数个数(NULL不是有效的参数需要减1)
int argc = sizeof(argv) / sizeof(argv[0]) - 1;
my_main(argc, argv);
return 0;
}

这种在容器尾部填充一个特殊结束标志值的技巧(如为argv数组额外的填充了一个NULL值),使得迭代访问元素很方便。
char **p = argv;
while (*p != NULL)
{
printf("%s\n", *p);
p++;
}
又如:
const int EOA = -1;
int arr[] = { 8, 3, 3, 2, 9, 4, 6, 7, EOA};
int *pa = arr;
while (*pa != EOA)
process(*pa++);
自定义参数
通过为main函数传递参数,就可以在程序启动时自定义行为,这些参数被称为“命令参数”,可以在项目属性中进行配置,各参数之间以空格分隔,参数自身含有空白的,加双引号限定,如:

#include <stdio.h>
int main(int argc, char *argv[])
{
for (int i = 0; i < argc; i++)
{
printf("argv[%d]: %s\n", i, argv[i]);
}
}

在CMD.EXE中运行
控制台程序也是可以独立运行的!对于图形化界面程序,双击启动程序后可以进入到窗口界面;而控制台程序如果没有特殊控制阻塞运行(如使用scanf读取数据),双击时会看到一个黑屏幕一闪而过。为此,我们可以选择在命令提示符下运行程序。
开启命令提示符可以有不限于以下两种方式:
- 打开运行对话框(Win+R键),输入cmd,按下回车键。
- 在Win10任务栏上单击搜索按钮,输入cmd,在搜索结果中选择命令提示符。
打开命令提示符后,我们可以选择直接运行程序,如:

也可以切换到程序所在目录下运行:
- 使用cd命令进入到应用程序所在文件夹(命令提示符窗口支持粘贴)
- 输入对应的盘符,切换到当前目录。
- 输入要执行的EXE文件名(对于可执行文件可省略后缀名.exe)

注意:在方法一中,命令提示符的当前工作目录c:\Users\glimix;而程序所在目录是F:\glimix\tutorials\Debug;即当前工作目录不是程序所在目录,此时argv[0]以绝对路径表示程序名称。而在方法二中,当前工作目录就是应用程序所在目录,argv[0]直接是程序名称。
现在我们尝试为程序提供额外的参数,来看一下运行结果。

做为教学目的,我们执行的是Debug模式下生成的程序。在实际环境下,发行到用户手中的程序应该是Release版本。Debug模式下生成的可执行程序中含有大量的调试信息,程序也没有被优化,相对于Release版本而言比较大,执行速度比较慢。在开发阶段通常使用Debug模式,方便我们调试测试,确保程序没有问题后,就可以生成Release版本供用户使用了。
查看main的返回值
对于程序
int main() { return -98765; }
当我们通过Visual Studio运行程序后,VS会在程序运行结束后发出提示,并打印出退出代码。

在脱离开发环境时,访问main的返回值的方法依赖于系统;在Windows系统中,执行完程序后,可以通过 echo %ERRORLEVEL% 获取其返回值。

正如之前所言,省略返回语句时,这等同于return 0;
int main() {}
