• 记一次函数异常(getopt_long)


    前言

    以下参考博客以及man手册。

    getopt_long函数,getopt_long函数包含了getopt函数的功能,并且还可以指定“长参数”(或者说长选项),与getopt函数对比,getopt_long比其多了两个参数:

    int getopt(int argc, char * const argv[], const char *optstring);
    int getopt_long(int argc, char * const argv[], const char *optstring,
     const struct option *longopts, int *longindex);
    

    在这里,longopts指向的是一个由option结构体组成的数组(数组最后一个成员必须是全0),那个数组的每个元素,指明了一个“长参数”(即形如–name的参数)名称和性质:

    struct option {
    	const char *name;
    	int	has_arg;
    	int     *flag;
    	int     val;
    };
    

    name 是参数的名称
    has_arg 指明是否带参数值,其数值可选:

    no_argument (即 0) 表明这个长参数不带参数(即不带数值,如:–name)
    required_argument (即 1) 表明这个长参数必须带参数(即必须带数值,如:–name Bob)
    optional_argument(即2)表明这个长参数后面带的参数是可选的,(即–name和–name Bob均可)

    flag 当这个指针为空的时候,函数直接将val的数值从getopt_long的返回值返回出去,当它非空时,val的值会被赋到flag指向的整型数中,而函数返回值为0
    val 用于指定函数找到该选项时的返回值,或者当flag非空时指定flag指向的数据的值。

    参数longindex,如果longindex非空,它指向的变量将记录当前找到参数符合longopts里的第几个元素的描述,即是longopts的下标值。

    一个小case

    // #pragma pack(push, 1)
    #include "unistd.h"
    #include "getopt.h"
    #include <string.h>
    #include <stdlib.h>
    #include <stdio.h>
    
    void ParserArgs(int argc, char **argv) {
        int opt = 0;
        int longIdx = 0;
        const char *optStr = "h";
        
        static struct option long_options[] = {
            {"proto",  required_argument, NULL, 201},
            {0, 0, 0, 0},
        };
        if (argv[argc-1][0] == '&') {
            argc -= 1;
        }
    
        while ( (opt = getopt_long(argc, argv, optStr, long_options, &longIdx)) != -1) {
            switch (opt) {
            case 201:
                printf("get %s
    ", optarg);
                break;
            case 'h':
            case '?':
                printf("aaaa using '-h' to get help");
                exit(0);
            default:
                printf("using '-h' to get help");
                exit(0);
            }
        }
    
    }
    
    int main(int argc, char ** argv) {
        ParserArgs(argc, argv);
        return 0;
    } 
    

    看到上面 #pragma pack(push, 1) 没有,如果把这个注掉,运行完美。
    但是如果打开就会有段错误。

    • 谁会把对齐写在这?
      • 我觉得这种情况是很有可能发生的。可能你不会写的这么直接,像这个例子一样。但是你可能包含了一个没有闭合对齐的头文件,它产生的结果和这是一样的。
      • 需要检查“pragma pack(push, n)”,“pragma pack(pop)”;“pragma pack(n)”,"pragma pack()"是否匹配。
    • 为什么不闭合对齐会有问题?
      • 我觉得和getopt_long本身有关,其中option参数是个结构指针,对齐会影响函数对参数的解析。
  • 相关阅读:
    机器学习笔记(一)线性回归模型
    为什么拷贝构造函数的参数可以直接去访问它自己的私有成员?
    C++之forward move源码分析
    C++之forward
    C++之不完整的数据类型释放
    C++中typename关键字的使用方法和注意事项(好文收藏)
    C++之左值引用和右值引用
    C++之Class内存
    C++ 之Const
    C++之DISALLOW_COPY_AND_ASSIGN
  • 原文地址:https://www.cnblogs.com/sinpo828/p/10678948.html
Copyright © 2020-2023  润新知