在讨论主函数参数前,我们先讨论为何需要主函数参数,它的参数是由谁来传递的。
ping命令
我们尝试在命令提示符中,使用ping.exe
这个可执行文件。
由于ping.exe
这个可执行文件在系统的搜索目录当中。所以,我们直接输入ping.exe
并回车,或者省略后缀名直接输入ping
并回车。命令提示符会在系统搜索目录中找到该可执行文件并执行。
执行ping
,会列出ping
它的用法和各种参数。
C:\Users\邬圣锋>ping
用法: ping [-t] [-a] [-n count] [-l size] [-f] [-i TTL] [-v TOS]
[-r count] [-s count] [[-j host-list] | [-k host-list]]
[-w timeout] [-R] [-S srcaddr] [-c compartment] [-p]
[-4] [-6] target_name
选项:
-t Ping 指定的主机,直到停止。
若要查看统计信息并继续操作,请键入 Ctrl+Break;
若要停止,请键入 Ctrl+C。
-a 将地址解析为主机名。
-n count 要发送的回显请求数。
-l size 发送缓冲区大小。
-f 在数据包中设置“不分段”标记(仅适用于 IPv4)。
-i TTL 生存时间。
-v TOS 服务类型(仅适用于 IPv4。该设置已被弃用,
对 IP 标头中的服务类型字段没有任何
影响)。
-r count 记录计数跃点的路由(仅适用于 IPv4)。
-s count 计数跃点的时间戳(仅适用于 IPv4)。
-j host-list 与主机列表一起使用的松散源路由(仅适用于 IPv4)。
-k host-list 与主机列表一起使用的严格源路由(仅适用于 IPv4)。
-w timeout 等待每次回复的超时时间(毫秒)。
-R 同样使用路由标头测试反向路由(仅适用于 IPv6)。
根据 RFC 5095,已弃用此路由标头。
如果使用此标头,某些系统可能丢弃
回显请求。
-S srcaddr 要使用的源地址。
-c compartment 路由隔离舱标识符。
-p Ping Hyper-V 网络虚拟化提供程序地址。
-4 强制使用 IPv4。
-6 强制使用 IPv6。
ping
这个可执行文件,用于向目标主机发送一个网络请求,目标主机若收到该请求将返回一个回应。通常用于测试目标主机和网络是否正常。
ping 114.114.114.114
C:\Users\邬圣锋>ping 114.114.114.114
正在 Ping 114.114.114.114 具有 32 字节的数据:
来自 114.114.114.114 的回复: 字节=32 时间=77ms TTL=67
来自 114.114.114.114 的回复: 字节=32 时间=87ms TTL=69
来自 114.114.114.114 的回复: 字节=32 时间=76ms TTL=66
来自 114.114.114.114 的回复: 字节=32 时间=74ms TTL=77
114.114.114.114 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 74ms,最长 = 87ms,平均 = 78ms
执行这段命令后,我们可以看到对目标主机114.114.114.114
发送了4次请求,并且目标主机了回复了这4次请求。每一次从请求直到收到回复耗时约80毫秒。这些信息说明,我们的电脑与目标主机114.114.114.114
之间的连接是通畅的。
ping baidu.com
C:\Users\邬圣锋>ping baidu.com
正在 Ping baidu.com [110.242.68.66] 具有 32 字节的数据:
来自 110.242.68.66 的回复: 字节=32 时间=72ms TTL=47
来自 110.242.68.66 的回复: 字节=32 时间=82ms TTL=47
来自 110.242.68.66 的回复: 字节=32 时间=72ms TTL=47
来自 110.242.68.66 的回复: 字节=32 时间=80ms TTL=47
110.242.68.66 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 72ms,最长 = 82ms,平均 = 76ms
执行这段命令后,我们可以看到对目标主机baidu.com
发送了4次请求,并且目标主机了回复这4次请求。每一次从请求直到收到回复耗时70到80毫秒。这些信息说明,我们的电脑与目标主机baidu.com
之间的连接也是通畅的。
在 windows 下,ping
发送4次请求后,就会终止了。可以附加上参数-t
让ping
不停地发送请求,直到按下Ctrl + C
键停止。
ping baidu.com -t
C:\Users\邬圣锋>ping baidu.com -t
正在 Ping baidu.com [110.242.68.66] 具有 32 字节的数据:
来自 110.242.68.66 的回复: 字节=32 时间=76ms TTL=47
来自 110.242.68.66 的回复: 字节=32 时间=75ms TTL=47
来自 110.242.68.66 的回复: 字节=32 时间=154ms TTL=47
110.242.68.66 的 Ping 统计信息:
数据包: 已发送 = 3,已接收 = 3,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 75ms,最长 = 154ms,平均 = 101ms
Control-C
^C
ping
发送了3次请求后,按下Ctrl + C
键停止程序
ping 10.0.0.0
C:\Users\邬圣锋>ping 10.0.0.0
正在 Ping 10.0.0.0 具有 32 字节的数据:
请求超时。
请求超时。
请求超时。
请求超时。
10.0.0.0 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 0,丢失 = 4 (100% 丢失),
执行这段命令后,我们可以看到对目标主机10.0.0.0
发送了4次请求,但是每一次目标主机都没有回复,直到等待时间超时。这些信息说明,我们的电脑与目标主机10.0.0.0
之间无法连接。
之前我们尝试了使用ping
命令向不同的目标主机发送请求。
接下来将讨论:不同的目标主机名和选项是如何传递到程序当中的
如果按照之前所学过的知识,可以调用scanf
等函数获取输入。但是,如果调用scanf
等输入函数,需要先运行可执行程序。待程序执行到输入函数时,才会读取输入。而在我们使用ping
命令时,把需要输入的字符串附带在可执行程序名ping
其后。例如:ping baidu.com -t
输入命令并按下回车后,命令提示符才会执行程序ping.exe
。很显然,此时程序还未运行。因此,这种机制不同于调用scanf
等输入函数。事实上,待程序执行后,这些命令字符串会被传递到主函数参数中。程序可以通过主函数参数,获取这些命令字符串。
主函数参数
带参数的主函数定义如下所示:
int main(int argc, char** argv)
{
return 0;
}
主函数的参数类型与数量是固定的,它可以带两个参数,分别是int
和char **
类型。参数名和其他函数一样可以自定义,但是惯例上使用argc
、argv
作为两个参数的参数名。
第一个参数名argc
为argument count
参数数量的缩写。
第二个参数名为argv
为argument value
参数值的缩写。
例如,我们使用如下命令启动 ping 这个可执行文件时。ping baidu.com -t
若主函数带有参数,那么第一个参数是值为3
,即命令拥有3个由空格分隔的字符串。
第二个参数是一个char **
类型的指针,它指向元素类型为char *
数组的首元素。数组中元素分别指向各字符串的首字符。
这3个字符串分别为:
ping
baidu.com
-t
从二级指针 argv 获取到字符串首元素指针有两种办法,它们是等价的:
- 使用指针移动和取值运算符。
- 使用下标。
使用取值运算符的写法:
*argv
指向第一个字符串的首字母*(argv + 1)
指向第二个字符串的首字母*(argv + 2)
指向第三个字符串的首字母
使用下标的写法:
argv[0]
指向第一个字符串的首字母argv[1]
指向第二个字符串的首字母argv[2]
指向第三个字符串的首字母
使用主函数参数
写一个程序,尝试使用主函数参数
#include <stdio.h>
int main(int argc, char** argv)//主函数带有了参数
{
printf("%d\n", argc);
for (int i = 0; i < argc; i++)
{
printf("%s\n", argv[i]);
}
return 0;
}
编译成功后,查看一下可执行文件的名称和所在目录。
C:\Users\邬圣锋>C1
'C1' 不是内部或外部命令,也不是可运行的程序
或批处理文件。
这是因为,C1.exe
不在系统的可执行文件搜索目录当中。因此,我们应当使用完整的路径来执行这个可执行文件。
绝对路径
可执行程序完整的路径为:C:\Git\C1\x64\Debug\C1.exe
这种完整的文件路径,被称作文件的绝对路径。在命令提示符里面输入可执行文件的绝对路径并回车,即可运行这个可执行文件。
C:\Users\邬圣锋>C:\Git\C1\x64\Debug\C1.exe
1
C:\Git\C1\x64\Debug\C1.exe
参数个数为1,字符串参数为:
C:\Git\C1\x64\Debug\C1.exe
在其后加上
have a good time
:
C:\Users\邬圣锋>C:\Git\C1\x64\Debug\C1.exe have a good time
5
C:\Git\C1\x64\Debug\C1.exe
have
a
good
time
参数个数为5,字符串参数分别为:
- C:\Git\C1\x64\Debug\C1.exe
- have
- a
- good
- time
相对路径
除了使用绝对路径,还可以使用以命令提示符的当前路径作为基准,通过相对的方式找到文件的位置。
这种路径被称作相对路径。
切换盘符
切换盘符输入盘符:
C:\Users\邬圣锋>D:
D:\>
cd
改变目录
cd
命令(change directory)是改变目录用的,但cd命令不能切换盘符
使用cd
命令,可以切换当前目录到C:\Git\C1\x64\Debug\
C:\Users\邬圣锋>D:
D:\>cd C:\Git\C1\x64\Debug\
D:\>
发现无法跳转,这是因为cd命令不能跨盘符跳转,需要先切换到C盘
C:\Users\邬圣锋>D:
D:\>cd C:\Git\C1\x64\Debug\
D:\>C:
C:\Git\C1\x64\Debug>
由于已经执行了D:\>cd C:\Git\C1\x64\Debug\
,C盘的目录已经跳转到了目标文件夹,切换到C盘时可以直接访问
dir
显示目录文件和子目录
使用dir
命令,可以看到当前目录下有刚刚编译的可执行文件C1.exe
。
C:\Git\C1\x64\Debug>dir
驱动器 C 中的卷是 Windows
卷的序列号是 7A3B-165E
C:\Git\C1\x64\Debug 的目录
2022/11/16 22:15 <DIR> .
2022/11/16 22:15 <DIR> ..
2022/11/16 22:15 62,464 C1.exe
2022/11/16 22:15 269 C1.exe.recipe
2022/11/16 22:15 592,048 C1.ilk
2022/11/16 22:15 56 C1.log
2022/11/16 22:15 937,984 C1.pdb
2022/11/16 22:15 <DIR> C1.tlog
2022/11/16 22:15 28 C1.vcxproj.FileListAbsolute.txt
2022/11/16 22:15 27,648 vc143.idb
2022/11/16 22:15 77,824 vc143.pdb
2022/11/16 22:15 9,317 源.obj
9 个文件 1,707,638 字节
3 个目录 274,681,638,912 可用字节
现在,可执行文件C1.exe
就在当前目录下。
使用相对路径
C1.exe
执行
C:\Git\C1\x64\Debug>C1.exe
1
C1.exe
可以省略后缀名
.exe
。
C:\Git\C1\x64\Debug>C1
1
C1
多加几个字符串试试看
C:\Git\C1\x64\Debug>C1 have a good time
5
C1
have
a
good
time
参数个数为5,字符串参数分别为:
- vs_demo
- have
- a
- good
- time
在Visual Studio中传递主函数参数
VS中运行结果
5
C:\Git\C1\x64\Debug\C1.exe
have
a
good
time