我对该C程序的工作方式的理解正确吗?

如何解决我对该C程序的工作方式的理解正确吗?

在以下程序中:

#include <unistd.h>
#include <stdio.h>
int main(int argc,char *argv[]) {
        char *delivery = "";
        int thick = 0;
        int count = 0;
        char ch;

        for (int i = 0; i < argc; i++) {
                fprintf(stdout,"Argv[%i] = %s\n",i,argv[i]); /* printing to understand (ptu) */
        }
        while ((ch = getopt(argc,argv,"d:t")) != -1)
                switch (ch) {
                        case 'd':
                                fprintf(stdout,"Optind in case 'd': %i\n",optind);
                                delivery = optarg;
                                break;
                        case 't':
                                fprintf(stdout,"Optind in case 't': %i\n",optind);
                                thick = 1;
                                break;
                        default:
                                fprintf(stderr,"Unknown option: '%s'\n",optarg);
                                return 1;
                }
        fprintf(stdout,"Argc: %i\n",argc); /* ptu */
        fprintf(stdout,"Argv: %p\n",argv); /* ptu */
        argc -= optind;
        argv += optind;
        fprintf(stdout,"Optind: %i. Argc after subtraction: %i,Argv after increment: %p\n",optind,argc,argv);
        if (thick)
                fprintf(stdout,"Thick crust!\n");
        if (delivery[0])
                fprintf(stdout,"To be delivered %s\n",delivery);
        fprintf(stdout,"Ingredients:\n");
        for (count = 0; count < argc; count++)
                fprintf(stdout,"%s\n",argv[count]);
        return 0;
}

当我使用下面显示的参数运行上述程序时,得到以下输出:

[u@h c]$ ./prog -t -d yesterday anchovies goatcheese pepperoni
Argv[0] = ./prog
Argv[1] = -t
Argv[2] = -d
Argv[3] = yesterday
Argv[4] = anchovies
Argv[5] = goatcheese
Argv[6] = pepperoni
Optind in case 't': 2
Optind in case 'd': 4
Argc: 7
Argv: 0x7ffebee8e498
Optind: 4. Argc after subtraction: 3,Argv index: 0x7ffebee8e4b8
Thick crust!
To be delivered yesterday
Ingredients:
anchovies
goatcheese
pepperoni

我想知道我对幕后情况的理解是否准确,特别是对于程序中的参数解析步骤而言。很抱歉没有分享更多的最低要求,但是在这种情况下,我可能无法。如果我可以向了解C的朋友展示这个消息,那么我就不会出现stackoverflow垃圾邮件。因此,请忍受我。什么都没有:

  1. 已定义main以接受命令行(cl)参数。这需要两个参数:

    • 整数argc,它将包含cl参数的数量,包括程序名称,在这种情况下为7
    • 字符串数组(即char指针数组),其每个元素将指向作为cl参数传入程序的每个字符串文字(存储在CONSTANT内存块中)的第一个元素的内存地址。
  2. for循环(自我解释)

  3. 在while循环的每次运行中,getopt()都会解析argv []数组,并将optstring "d:t"中的下一个匹配字符分配给字符变量ch,直到用完为止选项(不需要双关语),它将返回-1,并且控件将退出while循环。

      在每个这样的遍历optind中,
    • (由于argv [0]是程序名而在1处开始)将增加,以包含要在argv中处理的下一个元素的索引。 case 't',optind = <index of "-d" i.e. 2>case 'd',optind = <index of "anchovies" i.e. 4>中(这是因为getopt():的'd'之后的“ optstring”开始,{{ 1}}后面紧跟着其-d,因此optarg在这里增加到“ 4”,而不是“ 3”)
    • optind-t处理后,
    • -d yesterdaygetopt()中找不到与argv[]中的元素匹配的其他内容;因此它返回optstring,我们跳出了while循环。 -1仍设置为4,因为getopt在optstring的'-d之后没有找到其他内容。
  4. 我们现在将optind的{​​{1}}的值“ 4”递减,以确保我们跳过optind(我们已经解析过)到其余三个{{ 1}}参数。我们还将argc(最初指向option argumentsnon-option的内存位置增加argv,这就是为什么argv现在在内存中指向32字节的原因:{{1} }。换句话说,argv [0]指向“凤尾鱼”

  5. 然后我们根据argv[0]"./prog"的值打印内容,并循环遍历其余的非选项参数以同样打印它们...

解决方法

是的,您的理解是正确的。

我会提供两个注释:

  • “字符串文字”是指在程序中实际定义的字符串,为""分隔符之间的字符。 “ CONSTANT块”不是标准概念,但是我想您是指从二进制文件中加载的只读存储器块,因为这通常是字符串文字所在的位置。 argv指针所指向的字符串不是这种类型。不能,因为创建二进制文件时不知道它们。相反,它们位于未指定的内存区域中,并且您可以根据需要在适当的位置对其进行修改(尽管这可能会使您的代码令人困惑);例如argv[0][3] = 'x'是合法的。 (C17标准5.1.2.2.1(2))。

  • 有些人可能同样会发现在argc中修改argvmain的值会造成混淆,建议您将修改后的值分配给其他变量:

int remaining_argc = argc - optind;
char **remaining_argv = argv + optind;

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-