首页 > 解决方案 > 二维字符串数组的复合文字

问题描述

我在结构中有一个二维字符串数组,我希望能够在编译时使用复合文字初始化它,而不是使用 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]){
                ^~~~~~~~~~~~~~~~~~~~~~~
                {

所以,从这些警告中,我想我做错了什么。

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

标签: arrayscc99compound-literals

解决方案


结构定义不正确:正如定义的那样,labels是一个L_NUMKINDS指向char. 您可能想要labels指向nlabels指向. 定义应该更好,因为您想使用字符串常量作为初始化程序。L_NUMKINDScharchar *(*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 }

推荐阅读