为什么字符串可以工作,而字符和 int 数组在指针数组中不起作用?

Why do strings work, but character and int arrays do not work in a pointer array?

我理解如果我把数组st和st2加到内存里给它space,然后加到指针数组,应该没问题:

/* works */
int st[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
int st2[]= {0,31,29,31,30,31,30,31,31,30,31,30,31};
int *day_tab[]= {
        st,
        st2
};

但是没有先在内存中给它space,为什么字符串特别有效? 下面的代码给出了一个错误:

int *day_tab[]= {
        {0,31,28,31,30,31,30,31,31,30,31,30,31},
        {0,31,29,31,30,31,30,31,31,30,31,30,31}
};

下面的代码也是如此:

char *day_tab[]= {
        {'0','1','[=12=]'},
        {'0','1','[=12=]'}
};

但下面的代码有效

char *day_tab[]= {
        "01",
        "01"
};

这个

int st[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
int st2[]= {0,31,29,31,30,31,30,31,31,30,31,30,31};
int *day_tab[]= {
        st,
        st2
};

是三个数组:两个整数(有自己的存储空间)和一个包含两个元素的数组,这两个元素是指向前两个数组的指针。

但是,这是无效的:

int *day_tab[]= {
        {0,31,28,31,30,31,30,31,31,30,31,30,31},
        {0,31,29,31,30,31,30,31,31,30,31,30,31}
};

和之前一样,您已经声明了一个指向整数的指针数组,但是指针指向什么?那些花括号列表不是存储位置,无法指向它们。

你最后的例子基本有效但很危险:

char *day_tab[]= {
        "01",
        "01"
};

它是一个包含两个指向字符的指针的数组,这些指针是用字符串文字初始化的。字符串文字非常特殊,因为它们实际上存储在某个地方,通常在只读内存中,并且可以共享(因此使用两次的“01”字符串可以只存储一次)。大括号列表在 C 中没有此功能,它仅适用于字符串文字。

最终代码之所以危险,是因为它是 char* 而不是 const char*。出于向后兼容性的原因,可以接受非常量类型,但这不是一个好主意,因为不允许修改文字字符串中的数据。因此,如果您实际使用这些指针写入“01”字符串存储,那么您就是在为潜在的灾难做好准备。

以下作品

int *day_tab[]= {
        st,
        st2
};

因为当你访问一个数组时,它被转换为指向第一个元素的指针(很少有exceptions符合这个规则。因此,当您在初始化中使用 stst2 数组时,它们将转换为指向相应数组第一个元素的指针,并且在初始化后,指针 day_tab[0] 将指向数组 st 和指针 day_tab[1] 将指向数组 st1.

的第一个元素

在代码片段中

int *day_tab[]= {
        {0,31,28,31,30,31,30,31,31,30,31,30,31},
        {0,31,29,31,30,31,30,31,31,30,31,30,31}
};

char *day_tab[]= {
        {'0','1','[=12=]'},
        {'0','1','[=12=]'}
};

您正在尝试使用多个初始化程序初始化数组 day_tab 的指针。请注意,指针是 标量类型 并且来自 C11 标准#6.7.9p11

11 The initializer for a scalar shall be a single expression, optionally enclosed in braces....

但是,你可以使用compound literal来初始化day_tabint指针数组的指针,像这样:

    int *day_tab[]= {
        (int []){0,31,28,31,30,31,30,31,31,30,31,30,31},
        (int []){0,31,29,31,30,31,30,31,31,30,31,30,31}
    };

这将初始化指针 day_tab[0]day_tab[1] 以指向相应数组的第一个元素。 同样,对于 char 指针数组,你可以做

    char *day_tab[]= {
        (char []){'0','1','[=14=]'},
        (char []){'0','1','[=14=]'}
    };

当你这样做时

char *day_tab[]= {
        "01",
        "01"
};

之所以有效,是因为字符串文字是字符数组,当它在表达式中使用时,它将转换为指向数组第一个元素的 char 类型的指针。因此,这将指针 day_tab[0]day_tab[1] 初始化为指向 只读 字符串文字 "01".

的第一个元素