【问题标题】:getopt, optarg and optional parametersgetopt、optarg 和可选参数
【发布时间】:2014-01-14 21:03:44
【问题描述】:

这个问题特别关注 gcc 中可选参数的 getopt。当一个选项被定义为有一个可选参数并且没有给出参数时, optarg 被设置为一个空指针或一个指向空字符串的指针。该手册似乎没有处理这种情况。行为是否有保证?

巴里

【问题讨论】:

  • 欢迎来到 Stack Overflow。请尽快阅读About 页面。请注意,GCC 是一个 C 编译器,您可能会链接到不同系统上 getopt() 函数的不同实现。例如,如果您在 Solaris 上使用 GCC,您可能会使用getopt() 的 Solaris 实现,当您编写代码以使用 CLIP(命令行界面范式)扩展时,它相当强大,但它接近于 POSIX getopt() 当你不这样做时,而在 Linux 上,你可能会使用 getopt() 的 GLIBC 实现,它有一组不同的扩展。
  • 感谢您的所有帮助,这非常有用。我正在审查其他人的 17 年旧代码,它现在似乎反映了 POSIX getopt,而不使用该库。我会更仔细地研究并进一步考虑此事。

标签: c gcc getopt


【解决方案1】:

getopt 带有可选参数是 POSIX 函数的实现定义的扩展。如果文档中未说明其行为方式,则显式检查 optarg == NULL 是最安全的。如果不是NULL,我个人不会认为空字符串会表示缺少参数,但它可以。

当没有检测到参数时,我自己的实现将optarg 设置为NULL,但它可以很容易地指向包含0 字节的静态对象的内存地址作为读取的第一个字节,例如char noarg = 0; getopt 函数的源文件。顺便说一句,GNU libc 实现也将其设置为NULL,而没有记录当前的行为。

如果您想在发生任何一种行为时保持安全,尤其是由于缺乏文档,我建议您执行以下操作:

if (optarg && *optarg) {
    /* Argument present */
}
else {
    /* No argument */
}

【讨论】:

    【解决方案2】:

    如果您按照 POSIX getopt() 定义,则定义了行为:

    如果它检测到缺少选项参数,如果 optstring 的第一个字符是 <colon>,则它应返回 <colon> 字符 (':'),否则返回 <question-mark> 字符 ('?')。

    请注意,唯一可以检测到缺少选项参数的情况是最后一个参数是有效的选项字符之一并且没有额外的参数是缺少的参数。这意味着在任何命令的任何调用中都只能缺少一个参数(这真的没用)。

    如果你使用 GNU getopt,那么规则类似,但细节不同:

    此字符串中的选项字符后面可以跟一个冒号 (‘:’) 以表明它需要一个必需的参数。如果选项字符后跟两个冒号(‘::’),则其参数是可选的;这是一个 GNU 扩展。

    getopt 有三种方法来处理非选项 argv 元素后面的选项。特殊参数 ‘--’ 在所有情况下都强制结束选项扫描。

    这是一个夸大其词的说法,IIRC。如果-f 选项带有参数,则编写-f -- 会为您提供-- 的选项参数。

    • 默认是在扫描argv 的内容时对其进行置换,以便最终所有非选项都位于末尾。这允许以任何顺序给出选项,即使是编写的程序没有预料到这一点。
    • 如果选项参数字符串以连字符 (‘-’) 开头,则会进行特殊处理。它允许返回不是选项的参数,就好像它们与选项字符 ‘\1’ 关联一样。
    • POSIX 要求以下行为:第一个非选项停止选项处理。通过设置环境变量 POSIXLY_CORRECT 或以加号 (‘+’) 开头的选项参数字符串来选择此模式。

    getopt 函数返回下一个命令行选项的选项字符。当没有更多的选项参数可用时,它返回 -1。可能还有更多的非选项参数;您必须将外部变量 optindargc 参数进行比较才能检查。

    如果选项有参数,getopt 通过将参数存储在变量optarg 中返回参数。您通常不需要复制 optarg 字符串,因为它是指向原始 argv 数组的指针,而不是指向可能被覆盖的静态区域的指针。

    如果getoptargv 中找到不包含在options 中的选项字符,或者缺少选项参数,它会返回‘?’ 并将外部变量optopt 设置为实际的选项字符。如果选项的第一个字符是冒号 (‘:’),则 getopt 返回 ‘:’ 而不是 ‘?’ 以指示缺少选项参数。此外,如果外部变量opterr 不为零(这是默认值),getopt 会打印一条错误消息。

    这表示您需要查看来自getopt() 的返回值并将选项字符串的第一个字符设置为: 以了解何时缺少参数。同样,我记得你最终只能有一个可选参数,但自从我上次对系统提供的getopt() 变体进行任何广泛检查以来已经有好几年了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-05
      • 2013-09-27
      • 1970-01-01
      • 1970-01-01
      • 2016-11-07
      • 2010-11-06
      相关资源
      最近更新 更多