一个很长的选择,其中" val"碰巧是'0`?

时间:2017-07-22 04:45:03

标签: c glibc getopt

来自GNU C library manual

#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>

/* Flag set by ‘--verbose’. */
static int verbose_flag;

int
main (int argc, char **argv)
{
  int c;

  while (1)
    {
      static struct option long_options[] =
        {
          /* These options set a flag. */
          {"verbose", no_argument,       &verbose_flag, 1},
          {"brief",   no_argument,       &verbose_flag, 0},
          /* These options don’t set a flag.
             We distinguish them by their indices. */
          {"add",     no_argument,       0, 'a'},
          {"append",  no_argument,       0, 'b'},
          {"delete",  required_argument, 0, 'd'},
          {"create",  required_argument, 0, 'c'},
          {"file",    required_argument, 0, 'f'},
          {0, 0, 0, 0}
        };
      /* getopt_long stores the option index here. */
      int option_index = 0;

      c = getopt_long (argc, argv, "abc:d:f:",
                       long_options, &option_index);

      /* Detect the end of the options. */
      if (c == -1)
        break;

      switch (c)
        {
        case 0:
          /* If this option set a flag, do nothing else now. */
          if (long_options[option_index].flag != 0)
            break;
          printf ("option %s", long_options[option_index].name);
          if (optarg)
            printf (" with arg %s", optarg);
          printf ("\n");
          break;

        case 'a':
          puts ("option -a\n");
          break;

什么样的选项可以使程序到达case 0

printf("option %s", long_options[option_index].name);

是一个长期选项,其标志未设置,还是一个长期选项,其中&#34; val&#34;碰巧是0

什么样的选择&#34; {0,0,0,0}&#34;指定?

2 个答案:

答案 0 :(得分:1)

如果该选项设置了一个标志,即.flag 不是一个空指针,getopt_long() returns 0

  

如果flag不是空指针,则表示此选项应该设置   该计划中的一面旗帜。标志是你的int类型的变量   限定。将标志的地址放在标志字段中。放入val   字段您希望此选项存储在标志中的值。在   在这种情况下,getopt_long返回0。

示例代码在此处没有使用仅设置标志的选项;这种可能性稍后在example program中处理:

/* Instead of reporting ‘--verbose’
     and ‘--brief’ as they are encountered,
     we report the final status resulting from them. */
  if (verbose_flag)
    puts ("verbose flag is set");

{0, 0, 0, 0}仅仅是一个哨兵,因为option结构数组必须终止&#34;一个包含全零的元素。&#34;

编辑:

{ 0, 0, 0, 0 }内部使用全零(getopt_long())元素来确定何时到达option结构数组的末尾。发生这种情况时,返回值-1。示例代码中的while(1)循环首先检查这个循环,并在这种情况下终止循环:

/* Detect the end of the options. */
      if (c == -1)
        break;
  

哪种选项可以让计划覆盖case 0printf("option %s", long_options[option_index].name);

如果选项的.val字段恰好包含0,那么作为空指针的.flag将导致getopt_long()返回此值({{1 }})。 0中第一个if语句后面的代码检查这种可能性。这可能意味着在此示例代码中说明来自case 0的{​​{1}}的返回值本身可能不表示已设置标志。但这是一种特殊情况,示例中的数组元素不会导致达到0语句。这甚至可以被视为堕落的情况;最好避免在选项的getopt_long()字段中使用printf(),并避免在此处完全指定数值,以支持使用字符常量的约定,如示例中所做。如果采用此约定,则需要0字段中的.val值才能触发此行为。

答案 1 :(得分:1)

flag中的struct option字段为非NULL时,getopt_long将为该选项返回0,并且val字段的值存储在该地址中在flag中给出。

所以在上面的例子中,当&#34; verbose&#34;选项被给出,getopt_long将返回0并且verbose_flag被设置为1.类似地,对于&#34;简要说明&#34;选项,getopt_long将返回0,verbose_flag将设置为0.

数组末尾的所有字段设置为零的选项是一个标志,指示选项列表的结尾,而不是传入数组的长度。因为全零元素只是数组结束指示符而不是真正的选项,所以不需要处理它。

来自man page for getopt_long

  

longopts是指向作为

声明的struct option数组的第一个元素的指针
struct option {
    const char *name;
    int         has_arg;
    int        *flag;
    int         val;
};
     

不同领域的含义是:

     

名称

     

是长选项的名称。

     

has_arg

     

是:no_argument(或0)如果选项没有参数;   required_argument(或1)如果选项需要参数;要么   optional_argument(或2)如果选项采用可选参数。

     

标志

     

指定如何为long选项返回结果。如果flag为NULL,   然后getopt_long()返回val。 (例如,呼叫程序可以   将val设置为等效的短选项字符。)否则,   getopt_long()返回0,标志指向一个设置为的变量   val如果找到该选项,但如果该选项不是,则保持不变   找到。

     

VAL

     

是要返回的值,要么加载到指向的变量中   旗。

     

数组的最后一个元素必须用零填充。

关于什么类型的选项将超过break并在printf中调用case 0:flag的选项为0(或NULL),0为{ {1}},非空val将落在此处,即name。列表中没有这样的选项,因此代码不会被执行,但无论如何它可能都包含在对未来代码的安全检查中,可能会做类似的事情。