‘壹’ 解析命令行参数的函数
1.全局变量解释:
optarg: 如果选项带参数,参数保存在optarg中。如果选项带可选参数,而实际无参数时,optarg为NULL。
optind:argv数组中下一次需要处理的元素的下标,系统默认初始化此值为1. 0是没有意义的,argv[0]为程序名,在解析命令行参数中是没有意义的。getopt正常解析完毕后,optind设置为argv数组中第一个不是选项的元素的下标(一般为0)。
opterr:存储错误耐猛纳选项字符.
2. GNU/Linux的命令行选项有两种类型: 短选项和长选项昌没 ,前者以 '-' 作为前导符,后者以 '--' 作为前导符。 -n 表示是一个不带参数的短选项。 --n 表示是一个不带参数的长选项。现在有一个带有参数的短选项比如说 -w foo ,那么它和长选项 --foo 是等价的。
函数声明:
函数参数:
1.argc:主函数传递过来的实参
2.argv:主函数传递过来的实参
3.optstring:一个包含选项字符的字符串。 一组短选项组成的字符串
函数调用结果
1.该函数每解析完一个选项,就返回该选项字符。选项字符解析完毕后,调用getopt函数将会返回-1,然后optind设置为argv数组中第一个不是选项的元素的下标。
2. 当调用getopt函数检测到错误时(比如说检测到的选项字符不在optstring实参中),默认情况下函数返回'?'。 为什么说是默认呢?因为如果通过optstring实参指明选项带参数,而实际命令行没有参数时,getopt返回 ':' 而不是 '?'
关于optstring,还有几点说明:
1.如果选项带参数,该选项后接冒号,比如optstring这个实参值为"a:b",指示a带参数,b没有参数;
2.如果选项带可选参数,该选项后接两个冒号,比如"a::b",表明a可能有参数,也可能没有;
3.如果optstring的开头字符为':',表明如果指明选项带参数,而实际命令行没有参数时,getopt返回':'而不是'?'(默认情况下返回 '?' ,和无法识别的参数返回一样);
4.如果optstring的开头字符为'+',表明一但遇到一个非选项参数,马上停止扫描,随后的部分当作参数来解释;
5.如果optstring的开头字符为'-',表明如知贺果遇到无选项参数,则把它当作选项1(不是字符Ƈ')的参数
示例:(来源于man文档)
运行示例:
函数声明:
函数参数:
longops:指向一个option结构体数组的第一个元素。
longindex:getopt_long的最后一个参数longindex在函数返回时指向被搜索到的选项在longopts数组中的下标。
关于option struct如下:
注意在初始化option struct时: The last element of the array has to be filled with zeros.
函数返回值:
1.如果flag这个实参为null,那么这个函数返回val的值。 这样短选项字符解析和长选项解析搭建了桥梁。
2.如果flag这个实参不为null,那么这个函数返回0
3.选项字符解析完毕后,调用getopt_long函数将会返回-1
4.当调用getopt_long函数检测到错误时(比如说检测到的选项字符不在longops实参中),默认情况下函数返回'?'
示例:(来源于man 文档)
运行示例如下:
getopt_long_only类似于getopt_long,但是它把 '-' 开头的选项当作长选项来处理。如果该选项与长选项不匹配,而与短选项匹配,则可以作为短选项解析。
‘贰’ python笔记:命令行参数解析
有些时候我们需要通过命令行将参数传递给脚本,C语言中有个getopt()方法,python中也有个类似的命令行参数解析方法getopt()。python也提供了比getopt()更简洁的argparse方法。另外,sys模块也可以实现简单的参数解析,本文将对这3种命令行参数解析方法简要介绍。
sys.argv是传入的参数列表,sys.argv[0]是当前python脚本的名称,sys.argv[1]表示第一个参数,以此类推。
命令行运行:
可以看到传入的参数通过sys.argv来获取,它就是一个参数列表。
python的getopt与C语言的的getopt()函数类似。相比于sys模块,支持长参数和短参数,并对参数解析赋值。但它需要结合sys模块进行参数解析,语法格式如下:
短参数为单个英文字母,如果必须赋值需要在后面加英文冒号( : ),长参数一般为字符串(相比短参数,更能说明参数含义),如果必须赋值需要在后面加等号( = )。
命令行运行:
注意:短参数(options)和长参数(long_options)不需要一一对应,可以任意顺序,也可以只有短参数或者只有长参数。
argparse模块提供了很多可以设置的参数,例如参数的默认值,帮助消息,参数的数据类型等。argparse类主要包括ArgumentParser、add_argument和parse_args三个方法。
下面介绍这三个函数的使用方法。
argparse默认提供了 -h | --help 参数:
命令行运行:
下面列出部分参数:
下面来添加参数:
命令行运行:
parse_args() 方法用于解析参数,在前面的示例代码中使用parse_args方法来提取参数值,对于无效或者错误的参数会打印错误信息和帮助信息:
命令行运行:
本文介绍了Python的三种命令行参数解析方法sys.argv、getopt和argparse,可以根据自己的需要进行选择,getopt和argparse两种方法相比来说,建议选择argparse,代码量更少更简洁。更详细的使用方法参考官方文档:
--THE END--
‘叁’ 指令调度与命令行参数解析
编译器优化:指令调度
指令调度是指对程序块或过程中的操作进行排序以有效利用处理器资源的任务。其目的是通过重排指令提高指令级并行性,使得程序在具有指令流水线的CPU上更高效运行。指令调度优化的前提是CPU硬件支持指令并行。根据指令调度发生的阶段,可以分为静态调度和动态调度。静态调度发生在程序编译时期,由编译器完成,通过指令调度优化在生成可执行文件前完成指令重排。动态调度则发生在程序运行时期,需要提供硬件支持,比如乱序执行(OoOE)。现代计算机的指令并行方案有流水线、超标量和多核。其中,流水线和超标量与指令调度相关性更强,通过将指令执行过程分解为多个阶段以实现多条指令的执行时间重叠。指令调度与寄存器分配之间具有相互约束、相互作用的关系。指令调度通过降低指令间依赖提高程序并行度,改变指令执行时机会影响寄存器的生命周期。寄存器分配则通过缩短寄存器生命周期,尽量减少访存指令,影响指令调度。两者相互约束,联合求解可以得到更优的解决方案。在LLVM编译器中,寄存器分配前后都会执行指令调度。表调度是一种贪心+启发式方法,用于调度基本块中的指令,主要考虑数据依赖、硬件资源等信息。表调度的基本思想是维护ready列表和active列表,通过计算指令节点的优先级并在周期内调度指令以执行。数据型冒险、结构性冒险和控制型冒险是指令调度面临的主要约束,编译器通过插入NOP指令来化解冒险。表调度方法不能保证得到最优调度结果,但接近最优解。LLVM的命令行参数解析提供了一种方便的方法,简化了解析命令行参数、打印help信息等操作。通过引入LLVM Support库的cl::ParseCommandLineOptions函数,一行代码即可完成命令行参数解析功能。