首先使用命令行解析函数getopt与getopt_long函数需要包含如下头文件:

#include <unistd.h>
extern char *optarg;  //选项的参数指针
extern int optind,   //下一次调用getopt的时,从optind存储的位置处重新开始检查选项。 
extern int opterr,  //当opterr=0时,getopt不向stderr输出错误信息。
extern int optopt;  //当命令行选项字符不包括在optstring中或者选项缺少必要的参数时,该选项存储在optopt 中,getopt返回'?’、
int getopt(int argc, char * const argv[], const char *optstring);
int getopt(int argc, char * const argv[], const char * optstring);

其中 argc 和 argv 是main函数中的传递的参数个数和内容, optstring用来指定可以处理哪些选项, 下面是optstring的一个示例:
"a:bc"
该示例表明程序可以接受3个选项: -a -b -c, 其中 a 后面的 :表示该选项后面要跟一个参数, 即如 -a text的形式, 选项后面跟的参数会被保存到 optarg 变量中. 下面是一个使用示例:

#include <stdio.h>
#include <unistd.h>
int main(int argc, char **argv) {
    int ch;
    while((ch = getopt(argc, argv, "a:b")) != -1) {
        switch(ch) {
            case 'a':
                printf("option a: %s\n", optarg);
                break;
            case 'b':
                printf("option b \n");
                break;
            case '?': // 输入未定义的选项, 都会将该选项的值变为 ?
                printf("unknown option \n");
                break;
            default:
                printf("default \n");
        }
    }
}

程序输出:

[root c++]#./getopt -a 10 -b
option a: 10
option b

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
 
int main(int argc, char *argv[])
{
    int opt;
    char *optstring = "a:b:c:d";
 
    while ((opt = getopt(argc, argv, optstring)) != -1)
    {
        printf("opt = %c\n", opt);
        printf("optarg = %s\n", optarg);
        printf("optind = %d\n", optind);
        printf("argv[optind - 1] = %s\n\n",  argv[optind - 1]);
    }
 
    return 0;
}

程序输出:

[root@centos-linux-10 workspace]# ./getopt -a 1 -b 2 -c 3 -d
opt = a
optarg = 1
optind = 3
argv[optind - 1] = 1

opt = b
optarg = 2
optind = 5
argv[optind - 1] = 2

opt = c
optarg = 3
optind = 7
argv[optind - 1] = 3

opt = d
optarg = (null)
optind = 8
argv[optind - 1] = -d

通过上面的例子能比较清晰看到opt optarg optind等之间对应的关系。

getopt_long支持长选项的命令行解析, 所谓长选项就是诸如--help的形式, 使用该函数, 需要引入下面是函数原型:

#include <getopt.h>
int getopt_long(int argc, 
                char * const argv[],
                const char *optstring,
                const struct option *longopts,
                int *longindex);
int getopt_long_only(int argc,
                    char * const argv[],
                    const char *optstring,
                    const struct option *longopts,
                    int *longindex);

其中 argc , argv , optstring 和getopt中的含义一样, 下面解释一下longopts 和longindex
longopts 指向一个struct option 的数组, 下面是option的定义:

struct option {
    const char *name;
    int         has_arg;
    int        *flag;
    int         val;
};

下面是各字段的含义
name - 长选项的名称, 例如 help
has_arg - 是否带参数, 0 不带参数, 1 必须带参数, 2 参数可选
flag - 指定长选项如何返回结果, 如果flag为NULL, getopt_long() 会返回val. 如果flag不为NULL, getopt_long会返回0, 并且将val的值存储到flag中
val - 将要被getopt_long返回或者存储到flag指向的变量中的值

struct option opts[] = {
       {"version", 0, NULL, 'v'},
       {"name", 1, NULL, 'n'},
       {"help", 0, NULL, 'h'}
   };

我们来看{"version", 0, NULL, 'v'}, version 即为长选项的名称, 即按如下形式--version, 0 表示该选项后面不带参数, NULL 表示直接将v返回(字符v在ascii码中对应的数值), 即在使用getopt_long遍历到该条选项时, getopt_long 返回值为字符v对应的ascii码值.

longindex表示长选项在longopts中的位置, 例如在上面的示例中, version 对应的 longindex 为0, name 对应的 longindex 为1, help对应的 longindex 为2, 该项主要用于调试, 一般设为 NULL 即可.

在实际项目中的一个应用:

typedef struct longoption {
    int         val;      /**< equivalent short option char */
    const char* name;     /**< same as name in 'struct option' */
    int         has_arg;  /**< same as name in 'struct option' */
    const char* arg_name; /**< option arg name */
    const char* desc;     /**< option description, 包含用法和具体的取值 */
} option_t;


option_t mirror_mgt_disablelclmir_opts [] =
{
    {'-',0, 0, 0, "Description: "MIRROR_LOCALMIROR_DISABLE_DESC"\n\nUsages:\n  "MIRROR_LOCALMIROR_DISABLE_USAGE_SHORT"\n  "MIRROR_LOCALMIROR_DISABLE_USAGE_LONG},
    {'-',0, 0, 0, "Parameters:"},
    {'r', "reserve-lun",        LONGOPT_REQUIRE, NULL, " ""Input the LUN's name which will inherit the mirror-pair's mapping attribute"},
    {'f', "force", LONGOPT_NOPARAM,  NULL,  MIRROR_OPTIONAL" "MIRROR_LOCALMIROR_DISABLE_FORCE},
    {'h', "help",  LONGOPT_NOPARAM,   NULL, MIRROR_OPTIONAL" "MIRROR_MGT_HELP},
    {'-', 0, 0, 0, "Examples:\n   "MIRROR_LOCALMIROR_DISABLE_EXAMPLE},
    {0, 0, 0, 0, 0}
    
};