
9.6.3 指针数组作为main函数参数
指针数组有个重要应用,就是能作为main函数参数。
前面说过,C语言程序都是从main函数开始执行(由系统调用main函数)。当然,这个是从普通编程者的角度去看待,实际上在执行main函数之前系统还做了很多事情,但这些不需要去考虑。
目前程序中看到的main函数写法是这样的:

可以看到,main后面跟随的圆括号内是空的,没有内容。其实这个main函数是可以有参数的,也就是说系统调用main函数时,可以给main函数传递参数。
把main函数改造一下,该函数就能够接收系统传递进来的参数。把main定义行修改为如下内容:

请注意,main函数增加了两个形参,这样,这个main函数就能够接收两个传递进来的数据:①第一个形参是整型数据;②第二个形参是一个指针数组,这里是指针数组作为函数形参。虽然没有专门讲解指针数组作为函数形参,但在这里见过就等于认识了。
现在设置一下断点,看看默认情况下,系统调用main函数时,会传递给main函数什么样的参数内容,如图9.29所示。

图9.29 main函数传递进来的两个形参
观察图9.29,可以猜一下,argv是一个指针数组,这个数组的长度现在是1,那么观察一下可以看到,它这个元素的内容是可执行文件的完整路径文件名。
argc是一个数字,目前是1,目测好像argc里保存的是argv指针数组的长度,也就是argv指针数组的元素个数。
考虑一个问题:虽然main函数是系统调用的,并且系统可以给main函数传递形参,那么能不能人为地通过系统来给main函数传递额外的参数呢?其实是可以的,有两种方法。先讲述第一种。
第一种方法是可以专门在Visual Studio中进行实际操作的:
右击Visual Studio中左侧的“解决方案资源管理器”中的MyProject工程名,在弹出的快捷菜单中选择“属性”命令,这会弹出一个对话框,在对话框左侧单击“配置属性”下的“调试”选项,右侧在“命令参数”里就可以输入参数,根据上面看到的argv是一个字符型指针数组,可以猜到,能输入的参数就是很多个字符串,每个字符串之间要用空格隔开,例如这里输入a1b2c3并单击“确定”按钮,如图9.30所示。
然后写一段代码,就能够把在图9.30中在“命令参数”里输入的a1、b2、c3获取到并输出出来,这样就可以看到在程序中是可以接收到传递给main函数的参数的。
例如,Linux操作系统中有一个列文件命令如下:

这个命令中的“-la”就是一个参数,跟这里讲解的a1、b2、c3没有任何本质差别。现在把原来一些不需要的代码注释掉,写一些新代码如下:


图9.30 工程属性对话框

执行一下这段代码,看一看输出的结果,如图9.31所示。

图9.31 输出main函数中收到的各种参数内容
从这个结果猜测一下,刚刚在图9.30中输入了三个参数,分别是a1、b2、c3,这里接收到的argc=4,表示实际收到了4个参数,其中收到的第一个参数argv[0]已经看到了,它实际是这个可执行文件的完整路径文件名,据此可以断定,系统传递给main函数的argv参数(指针数组)中的第一个元素肯定是该可执行文件的完整路径文件名,而后系统才会依次把输入的参数a1、b2、c3传递给main函数的argv参数。
上面的代码,for循环还可以修改一下。修改后的写法如下,如果看不太懂,及时设置断点调试观察:

通过这个范例,可以看出指针数组作为函数参数的一个优势,因为向main函数传递参数时,参数的个数并不确定,每个参数的长度也不确定,所以用指针数组能够比较好地满足这种灵活性的要求。
刚刚说过,人为地通过系统来给main函数传递额外的参数有两种方法,现在讲述第二种方法,就是直接在命令行输入可执行文件名并在后面跟随着参数。
在目录C:\Users\KuangXiang\Desktop\C++\MySolution\Debug下有一个可执行文件MyProject.exe,是刚刚编译生成的可执行文件(.exe文件),可以用cmd命令打开一个DOS黑窗口,在黑窗口中用cd命令跳转到该exe文件所在的目录,直接通过命令行执行这个可执行文件并给这个可执行文件传递参数,如图9.32所示。

图9.32 在命令行执行exe文件并为其传递运行时参数
可以看到,结果一样,程序接收到了通过命令行提供的参数,并且把接收到的参数内容输出了。