main 函数
main 函数是 C 程序的入口点,程序从这里开始执行。C99 标准规定了 main 的两种标准形式,其他形式(如 void main())不是标准 C,不可移植。理解 main 的参数和返回值,是编写正确 C 程序的基础。
标准形式
C99 允许两种 main 形式:
/* 形式 1:无参数 */
int main(void)
{
/* ... */
return 0;
}
/* 形式 2:命令行参数 */
int main(int argc, char *argv[])
{
/* ... */
return 0;
}
形式 1:int main(void)
不接受任何参数。void 表示"无参数",不是"任意参数"。
形式 2:int main(int argc, char *argv[])
argc(argument count):命令行参数的数量,至少为 1(程序名本身)argv(argument vector):字符串数组,每个元素是一个参数
int main(int argc, char *argv[])
{
printf("Program name: %s\n", argv[0]);
printf("Number of arguments: %d\n", argc);
for (int i = 1; i < argc; i++)
printf("Argument %d: %s\n", i, argv[i]);
return 0;
}
运行:
./program hello world 123
输出:
Program name: ./program
Number of arguments: 4
Argument 1: hello
Argument 2: world
Argument 3: 123
返回值
main 的返回值被操作系统接收,作为程序的退出状态:
0或EXIT_SUCCESS:正常退出- 非零或
EXIT_FAILURE:异常退出
#include <stdlib.h>
int main(void)
{
FILE *fp = fopen("data.txt", "r");
if (fp == NULL) {
perror("Cannot open file");
return EXIT_FAILURE; /* 1 */
}
/* 处理文件 */
fclose(fp);
return EXIT_SUCCESS; /* 0 */
}
C99 规定:如果 main 执行到末尾没有 return,等效于 return 0;。但显式写 return 0; 是更好的习惯。
非标准形式
以下形式不是标准 C,某些编译器可能接受,但不可移植:
void main(void) /* 错误:返回类型必须是 int */
{
/* ... */
}
main() /* C89 允许(隐式 int),C99 错误 */
{
/* ... */
}
int main(int argc, char **argv, char *envp[]) /* 某些系统的扩展 */
{
/* envp 是环境变量数组,非标准 */
}
命令行参数解析
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
if (argc < 3) {
printf("Usage: %s <input> <output>\n", argv[0]);
return EXIT_FAILURE;
}
const char *input_file = argv[1];
const char *output_file = argv[2];
/* 可选参数 */
int verbose = 0;
for (int i = 3; i < argc; i++) {
if (strcmp(argv[i], "-v") == 0)
verbose = 1;
}
printf("Input: %s\n", input_file);
printf("Output: %s\n", output_file);
if (verbose)
printf("Verbose mode on\n");
return EXIT_SUCCESS;
}
常见错误
void main:
void main(void) /* 错误:返回类型必须是 int */
{
/* ... */
}
某些教材和旧代码使用 void main(),这不是标准 C。Windows 的某些编译器接受它,但 Linux/Unix 系统期望 int 返回值。
忘记 return:
int main(void)
{
printf("Hello\n");
/* C99 之前:未定义行为 */
/* C99:等效于 return 0; */
}
虽然 C99 允许省略末尾的 return,但显式写更明确。
argv 越界访问:
int main(int argc, char *argv[])
{
printf("%s\n", argv[1]); /* 错误:如果没有参数,argv[1] 越界 */
/* 正确 */
if (argc > 1)
printf("%s\n", argv[1]);
else
printf("No arguments\n");
return 0;
}
最佳实践
- 始终使用
int main(void)或int main(int argc, char *argv[]) - 显式写
return 0;或return EXIT_SUCCESS; - 使用
EXIT_SUCCESS和EXIT_FAILURE宏 - 检查
argc再访问argv[i] - 提供使用说明(
argv[0]是程序名) - 不要依赖 C99 的隐式
return 0