通过实验,看来我可以在迭代optarg
的同时捕获int getopt(int argc, char * const argv[], const char *optstring)
的连续值,并在以后引用它们,如以下示例程序所示:
// main.c
#include <stdio.h>
#include <unistd.h>
int main( int argc, char* argv[] )
{
int opt;
char o;
char* a = NULL;
char* b = NULL;
while ( -1 != ( opt = getopt( argc, argv, "abcd:e:" ) ) )
{
char o = opt & 0xFF;
switch ( o )
{
case 'a':
{
printf( "%c (%p): [%s]\n", o, optarg, (NULL == optarg ? "" : optarg ) );
break;
}
case 'b':
{
printf( "%c (%p): [%s]\n", o, optarg, (NULL == optarg ? "" : optarg ) );
break;
}
case 'c':
{
printf( "%c (%p): [%s]\n", o, optarg, (NULL == optarg ? "" : optarg ) );
break;
}
case 'd':
{
printf( "%c (%p): [%s]\n", o, optarg, (NULL == optarg ? "" : optarg ) );
a = optarg;
break;
}
case 'e':
{
printf( "%c (%p): [%s]\n", o, optarg, (NULL == optarg ? "" : optarg ) );
b = optarg;
break;
}
}
}
printf( "(%p): [%s]\n", a, (NULL == a ? "" : a ) );
printf( "(%p): [%s]\n", b, (NULL == b ? "" : b ) );
return 0;
}
编译和示例执行:
> gcc -g main.c && ./a.out -dabc -e def -a
d (0x7fffe8d1d2b2): [abc]
e (0x7fffe8d1d2b9): [def]
a ((nil)): []
(0x7fffe8d1d2b2): [abc]
(0x7fffe8d1d2b9): [def]
问题:这有效吗?即在optarg
的连续迭代和/或其最终迭代(返回-1时)之后,连续的非NULL getopt()
值是否有效?即捕获连续的值并在以后引用它们(即不strdup
对其进行引用)是否安全?我不想假设我的实验代码通常是正确的。
该手册页指出存在一个 extern char* optarg
,但未指定是否可以通过连续调用getopt()
来重用。
(由于getopt
的参数是argc
和argv
,这意味着将optarg
设置为argv
的偏移量,在这种情况下,我可以想象它可以安全地捕获其连续值,但是我想了解这是否是正确的假设)。
答案 0 :(得分:3)
根据POSIX specification of getopt
:
getopt ()函数应从 argv 返回与 optstring 中的字符匹配的下一个选项字符(如果找到)。如果有一个匹配。如果选项带有参数,则 getopt ()应将变量 optarg 设置为指向选项参数,如下所示:
如果选项是 argv 元素指向的字符串中的最后一个字符,则 optarg 应包含< em> argv 和 optind 应加2。如果 optind 的结果值大于 argc ,这表明缺少选项参数,并且 getopt ()将返回错误指示。
否则, optarg 将指向 argv 的该元素中选项字符之后的字符串,并指向 optind 应增加1。
(强调我的。)
这表示optarg
始终指向argv
的元素。它永远不会复制。
由于argv
的元素在程序运行期间一直有效,因此您的代码有效(无需复制)。
NB。 POSIX页面上还显示了一个example of command line options with arguments,它基本上与您的版本等效:
char *ifile;
...
while ((c = getopt(argc, argv, ":abf:o:")) != -1) {
switch(c) {
...
case 'f':
ifile = optarg;
break;
...
答案 1 :(得分:0)
getopt状态的手册页:
optstring是包含合法选项字符的字符串。如果 此类字符后接冒号,该选项需要一个参数- ,因此getopt()将指针指向以下文本 optv中的argv-element或以下argv-element的文本
还有:
默认情况下,getopt()会在扫描时置换argv的内容,以便 最终所有非选项都在末尾。
这意味着,它不会分配任何内存,也不会将文本存储在静态缓冲区中,而是直接在您提供的argv
指针数组上工作,仅在其中提供地址。
您可以在代码中验证此行为:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char **argv) {
int opt, cur;
while (-1 != (opt = getopt(argc, argv, "a:b:c:"))) {
cur = optind - 1;
printf("current elemnt = %d argv[%d] = %p optarg = %p delta = %d\n",
cur, cur, argv[cur], optarg, (int)(optarg - argv[cur]));
}
return 0;
}