【问题标题】:Initialize an array of strings using scalar initializer使用标量初始化器初始化字符串数组
【发布时间】:2021-05-10 11:43:04
【问题描述】:

我是 C 的新手,如果这个问题变得微不足道,我很抱歉。我已经使用宏(现在)编写了一个项目结构初始化,它接受一个方法和一个字符串数组作为方法参数。最后一个参数的初始化会引发有关标量初始化程序中元素过多的警告。

item 是一个包含名称、方法和方法参数的小结构。如您所见,最后一个字段被声明为字符串数组。

// Definition of mcl_item; aka. mitem
struct mcl_item {
    char *name;
    void (*method)(char *args[]);
    char **args;
};
#define mitem struct mcl_item

// Create a new mitem (user will use item and item0 macros instead)
mitem new_mitem(char name[MAX_STRLEN], void (*method)(char **), int n, char *arg, ...) {
    // return simple mitem without arguments allocation
    return((mitem){
        .name = name,
        .method = method,
        .args = 0
    });
}

这就是我的宏的样子,这也是我认为标量初始化应该起作用的:

// Define arguments amount by a macro
#define ARGSN(...) (int)(sizeof((char *){__VA_ARGS__})/sizeof(char *))
// Overload new_mitem() to avoid taking n parameter storing generated size
#define NEW_MITEM(name, method, ...) \
    new_mitem(name, method, ARGSN(__VA_ARGS__), (char *){__VA_ARGS__})
// Top level macro for creating item with arguments
#define item(name, method, ...) NEW_MITEM(name, method, __VA_ARGS__)
// Top level macro for creating item without arguments
#define item0(name, method) NEW_MITEM(name, method, 0)

然后在主程序内部初始化项目并访问它们。

// Boilerplate methods used by items
void hello(char *args[]);
void extend(char *args[]);

int main() {
    // initialize items
    mitem item1 = item("extend", &extend, "Charlie", "Delta");
    mitem item2 = item0("hello", &hello);
    // access item1
    printf("Accessing item: %s\n", item1.name);
    item1.method(item1.args);
    // access item2
    printf("Accessing item: %s\n", item2.name);
    item2.method(item2.args);
    
    return(0);
}

// Boilerplate methods definitions
void hello(char *args[]) {
    char name[MAX_STRLEN] = "Bob";
    if (!args[0]) {
        strcpy(name, args[0]);
    }
    printf("Hello %s!\n", name);
}

void extend(char *args[]) {
    hello(args);
    printf("Welcome %s.\n", args[1]);
}

带有-E标志预编译的gcc响应:

<source>:43:91: warning: excess elements in scalar initializer
   43 |     struct mcl_item item1 = new_mitem("extend", &extend, (int)(sizeof((char *){"Charlie", "Delta"})/sizeof(char *)), (char *){"Charlie", "Delta"});
      |                                                                                           ^~~~~~~
<source>:43:91: note: (near initialization for '(anonymous)')
<source>:43:138: warning: excess elements in scalar initializer
   43 |     struct mcl_item item1 = new_mitem("extend", &extend, (int)(sizeof((char *){"Charlie", "Delta"})/sizeof(char *)), (char *){"Charlie", "Delta"});
      |                                                                                                                                          ^~~~~~~
<source>:43:138: note: (near initialization for '(anonymous)')

【问题讨论】:

  • 是的,对不起。我想这就是你现在所需要的。
  • 只需使用 -E 选项并查看预处理代码 godbolt.org/z/Mcnnvz 。然后开始相应地改变你的宏
  • 不过,我看不出这个初始化有什么问题,为什么“Delta”错了:struct mcl_item item1 = new_mitem("extend", &amp;extend, (int)(sizeof((char *){"Charlie", "Delta"})/sizeof(char *)), (char *){"Charlie", "Delta"});

标签: arrays c string initialization


【解决方案1】:

在使用时,(char *){__VA_ARGS__} 将替换为 (char *){"Charlie", "Delta"}。这表示创建一个char * 并使用"Charlie""Delta" 对其进行初始化。然而,char * 是一回事(指向 char 的指针),"Charlie""Delta" 是两回事。因此编译器会警告你有太多的初始化器。

您可以使用(char *[]){__VA_ARGS__} 创建指向char * 的指针数组。当用作sizeof 的操作数(或作为一元&amp; 的操作数)时,这将给出数组的大小,因此它将在ARGSN 宏中起作用。否则,数组将自动转换为指向其第一个元素的指针,因此可用于初始化args 成员或其他char ** 对象。

但是,您的new_mitem 函数不采用char ** 参数,而是声明char *arg, ...。你要么想把它传递给__VA_ARGS__,要么把它改成char **arg(没有...)然后把它传递给(char *[]){__VA_ARGS__}

【讨论】:

  • 我现在将__VA_ARGS__ 作为最后一个参数直接传递给new_mitem() 方法;我已经删除了char *arg 参数,正如我在阅读man 3 stdarg 时发现的那样,最后一个参数的类型并不重要。但是我从最后一个参数中得到的仍然只是一个字符串"Charlie"。像"Delta" 在初始化中不起作用。
  • @DanielFreeman:如何处理变量参数是一个单独的问题。
  • 感谢您指导我。你能帮我弄清楚我在变量处理方面做错了什么,或者我应该为此启动一个新线程吗?我发布了我当前的代码here
  • 好的.. 我只是放弃所有va_arg 业务并使用简单的指针,更容易且不那么烦人。
猜你喜欢
  • 2011-05-15
  • 2011-12-11
  • 1970-01-01
  • 2017-06-14
  • 1970-01-01
  • 1970-01-01
  • 2013-01-08
  • 2016-03-15
相关资源
最近更新 更多