为何char* argv[argc+1]在Visual Studio中报错?
关于《Modern C》中main函数参数写法的疑问解答
问题背景
我正在通过Jens Gustedt所著的《Modern C》学习C语言,书中示例代码的main函数定义如下:
#include <stdlib.h> #include <stdio.h> /* lower and upper iteration limits centered around 1.0 */ static double const eps1m01 = 1.0 - 0x1P-01; static double const eps1p01 = 1.0 + 0x1P-01; static double const eps1m24 = 1.0 - 0x1P-24; static double const eps1p24 = 1.0 + 0x1P-24; int main (int argc, char* argv[argc+1]) { for (int i = 1; i < argc; ++i) { // process args double const a = strtod(argv[i], 0); // arg -> double double x = 1.0; for (;;) { // by powers of 2 double prod = a * x; if (prod < eps1m01) { x *= 2.0; } else if (eps1p01 < prod) { x *= 0.5; } else { break; } } printf("x: %f\n", x); for (;;) { // Heron approximation double prod = a * x; if ((prod < eps1m24) || (eps1p24 < prod)) { x *= (2.0 - prod); } else { break; } } printf("heron: a = % .5e,\tx = % .5e,\ta * x = % .12f\n", a, x, a * x); } return EXIT_SUCCESS; }
使用Visual Studio编译时,char* argv[argc+1]中的argc+1会报错,移除argc+1改成char* argv[]后程序可以正常运行,想了解:
- 这样修改是否会改变程序功能?
- 原书中的写法是否属于过时的参数写法?
解答
1. 修改后程序功能完全不变
在C语言中,函数参数里的数组声明会被编译器自动退化为指针。也就是说:
char* argv[argc+1]char* argv[]char** argv
这三种写法在编译器看来完全等价,最终都会被处理成指向char*类型的指针。原书中的argc+1只是用来语义化描述argv的实际结构(argv确实是一个包含argc+1个元素的数组,最后一个元素为NULL),但对程序的实际运行逻辑没有任何影响。所以去掉argc+1后,程序功能和原代码完全一致。
2. 原写法并非过时,而是C99标准的特性
char* argv[argc+1]是C99标准引入的变长数组(VLA)作为函数参数的写法,目的是让代码的语义更清晰,明确argv的元素数量。它不仅不过时,反而属于更现代的C语言写法。
报错的原因是Visual Studio的C编译器对C标准的支持存在滞后性,早期版本完全不支持C99的VLA特性,直到较新的版本才部分支持。所以在VS环境下,改用char* argv[]或char** argv这种兼容所有C编译器的标准写法即可。
内容的提问来源于stack exchange,提问作者Jodlak
相关产品推荐
相关产品推荐

