【问题标题】:Compound literal for two-dimensional array of strings二维字符串数组的复合文字
【发布时间】:2021-12-11 08:19:25
【问题描述】:

我在结构中有一个二维字符串数组,我希望能够在编译时使用复合文字初始化它,而不是使用 malloc() 动态初始化它。

这个字符串数组的含义是它是一个项目数组,每个项目有三个字符串(一个是项目的名称,另一个是描述,另一个是 URL)。

是的,我知道我可以使用三个数组,但我更愿意将它打包成一个二维数组。

我试图这样写(注意我只是初始化项目的名称,而不是描述或 URL……这是故意的,因为我假设指向描述和 URL 的指针将根据指定的初始化器行为自动初始化为NULL——当你不初始化一个字段时,它变成零)

我的尝试:

enum labelkind {
    L_NAME,
    L_DESCRIPTION,
    L_URL,
    L_NUMKINDS};
    
struct labeltype{
    int someval;
    size_t  nlabels;
    char    **labels[L_NUMKINDS];
    };
    
static struct labeltype mylabel = {
    .someval=10,
    .nlabels=3,
    .labels=(char *[][L_NUMKINDS]){
        [0][L_NAME]="First name",
        [1][L_NAME]="Second name",
        [2][L_NAME]="Third name"
        }
    };

用 clang 编译它,我收到以下警告:

main.c:266:10: warning: incompatible pointer types initializing 'char **' with an expression of type 'char *[3][3]'
      [-Wincompatible-pointer-types]
        .labels=(char *[][L_NUMKINDS]){
                ^~~~~~~~~~~~~~~~~~~~~~~
main.c:266:10: warning: suggest braces around initialization of subobject [-Wmissing-braces]
        .labels=(char *[][L_NUMKINDS]){
                ^~~~~~~~~~~~~~~~~~~~~~~
                {

所以,根据这些警告,我想我做错了什么。

这样做的正确语法是什么?

【问题讨论】:

    标签: arrays c c99 compound-literals


    【解决方案1】:

    结构定义不正确:根据定义,labels 是一个由L_NUMKINDS 指针组成的数组,指向char 的指针。您可能希望labels 指向nlabels 数组L_NUMKINDS 指向char 的数组。定义应该是 char *(*labels)[L_NUMKINDS]; 或更好的 const char *(*labels)[L_NUMKINDS];,因为您想使用字符串常量作为初始化器。

    这是一个带有测试程序的修改版本:

    #include <stdio.h>
    
    enum labelkind {
        L_NAME,
        L_DESCRIPTION,
        L_URL,
        L_NUMKINDS
    };
    
    struct labeltype {
        int someval;
        size_t nlabels;
        const char *(*labels)[L_NUMKINDS];
    };
    
    static struct labeltype mylabel = {
        .someval = 10,
        .nlabels = 4,
        .labels = (const char *[][L_NUMKINDS]) {
            [0][L_NAME] = "First name",
            [1][L_NAME] = "Second name",
            [2][L_NAME] = "Third name",
            [3][L_NAME] = "Fourth name",
        }
    };
    
    static void pstr(const char *name, const char *s) {
        printf("%s: ", name);
        if (s)
            printf("\"%s\"", s);
        else
            printf("null");
    }
    
    static void print_labels(const struct labeltype *lp) {
        for (size_t i = 0; i < lp->nlabels; i++) {
            printf("{ ");
            pstr("name", lp->labels[i][L_NAME]);
            printf(", ");
            pstr("description", lp->labels[i][L_DESCRIPTION]);
            printf(", ");
            pstr("url", lp->labels[i][L_URL]);
            printf(" }\n");
        }
    }
    
    int main() {
        print_labels(&mylabel);
        return 0;
    }
    

    输出:

    { name: "First name", description: null, url: null }
    { name: "Second name", description: null, url: null }
    { name: "Third name", description: null, url: null }
    { name: "Fourth name", description: null, url: null }
    

    【讨论】:

    • 非常感谢,@chqrlie。我想做的是 Nx3 字符串的二维数组,所以它要么是 char **[3] 要么是 char *[][3] 。你的代码是一维字符串数组,我需要二维的。
    • @cesss:定义实际上应该是const char *(*labels)[L_NUMKINDS];,复合文字应该读作(const char *[][L_NUMKINDS]) { ... }
    • 就是这样,@chqrlie!括号!恐怕我需要用 K&R 书中的dcl 工具来练习!!非常感谢。
    • 我已经练习 C 定义近 40 年了,包括实现解析器和编译器,但它仍然困扰着我。 C99 结构增加了复杂性,但收益微乎其微,但实现者却很痛苦。保持好心情,享受旅行:)
    • 尝试使用螺旋规则解析 C 定义:从标识符开始,向右解析,当你遇到) 括号时,向标识符左侧解析,当你遇到(跳过() 并向右解析,等等。const char *(*labels)[L_NUMKINDS]; 是指向L_NUMKINDS 字符串指针数组s 的指针。
    猜你喜欢
    • 2021-06-12
    • 2016-05-06
    • 1970-01-01
    • 1970-01-01
    • 2015-12-16
    • 2010-10-16
    • 2016-08-10
    • 2019-09-14
    • 1970-01-01
    相关资源
    最近更新 更多