You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

getopt_long/get_opt是否移动argv指针?改写get_some_switches相关疑问

关于用getopt_long()改写get_some_switches()的疑问与解答

需要用getopt_long()改写Larry Wall补丁1.3中的get_some_switches()函数,原函数代码如下:

get_some_switches()
{
register char *s;

rejname[0] = '\0';
if (!Argc)
    return;
for (Argc--,Argv++; Argc; Argc--,Argv++) {
    s = Argv[0];
    if (strEQ(s,"+")) {
        return; /* + will be skipped by for loop */
    }
    if (*s != '-' || !s[1]) {
        if (filec == MAXFILEC)
            fatal("Too many file arguments.\n");
        filearg[filec++] = savestr(s);
    }
    else {
        switch (*++s) {
        case 'b':
            origext = savestr(Argv[1]);
            Argc--,Argv++;
            break;
        case 'c':
            diff_type = CONTEXT_DIFF;
            break;
        case 'd':
            if (chdir(Argv[1]) < 0)
                fatal("Can't cd to %s.\n",Argv[1]);
            Argc--,Argv++;
            break;
        case 'D':
            do_defines++;
            Sprintf(if_defined, "#ifdef %s\n", Argv[1]);
            Sprintf(not_defined, "#ifndef %s\n", Argv[1]);
            Sprintf(end_defined, "#endif %s\n", Argv[1]);
            Argc--,Argv++;
            break;
        case 'e':
            diff_type = ED_DIFF;
            break;
        case 'l':
            canonicalize = TRUE;
            break;
        case 'n':
            diff_type = NORMAL_DIFF;
            break;
        case 'o':
            outname = savestr(Argv[1]);
            Argc--,Argv++;
            break;
        case 'p':
            usepath = TRUE; /* do not strip path names */
            break;
        case 'r':
            Strcpy(rejname,Argv[1]);
            Argc--,Argv++;
            break;
        case 'R':
            reverse = TRUE;
            break;
        case 's':
            verbose = FALSE;
            break;
#ifdef DEBUGGING
        case 'x':
            debug = atoi(s+1);
            break;
#endif
        default:
            fatal("Unrecognized switch: %s\n",Argv[0]);
        }
        }
    }
}

原函数通过循环递减Argc、递增Argv处理参数,遇到'+'或参数耗尽时停止,后续调用该函数时Argc和Argv已指向参数列表的后续位置。针对改写中的疑问,解答如下:

疑问解答

1. getopt_long和getopt是否会推进argv指针?

  • getopt和getopt_long不会直接修改argv指针本身,它们通过全局变量optind记录下一个待处理的参数索引。每次调用函数时,会基于optind的值读取argv数组的对应元素,处理完成后自动递增optind——这相当于间接推进了参数处理的位置,但argv数组的指针不会被改变。

2. 使用getopt_long替代原函数时,是否需要手动更新Argc和Argv以支持后续调用,还是getopt_long会保留上次处理的位置?

  • 不需要手动更新Argc和Argv。getopt_long依赖全局变量optind追踪当前处理进度,只要不手动重置optind,后续调用会自动从上次停止的位置继续处理参数。
  • 注意:首次调用前需确保optind初始化为1(因为argv[0]是程序名,不属于命令行选项);如果需要重新从头处理参数,才需要手动将optind重置为1。

3. 原代码中的条件!s[1]表示什么含义?

  • 原代码中s指向当前参数字符串(即Argv[0]),!s[1]表示当前参数是单独的-字符,没有后续选项字符。比如用户输入./program -时,s指向字符串"-",s[1]是字符串结束符'\0',!s[1]结果为真。此时原代码会把这个单独的-当作普通文件参数处理,而非命令行选项。

内容的提问来源于stack exchange,提问作者eternallymisty

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 07:07:51