我明白如果我添加数组,st和st2,在内存中给它空间,然后将其添加到指针数组,它不应该是一个问题:
/* 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
};
但是没有首先给它内存空间,为什么字符串特别工作?下面的代码给出一个错误:
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',' '},
{'0','1',' '}
};
但是下面的代码可以工作
char *day_tab[]= {
"01",
"01"
};
This
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*
。出于向后兼容的原因,非const类型是可以接受的,但这不是一个好主意,因为不允许修改文字字符串中的数据。所以如果你真的用这些指针写" 01 "的话你就会有潜在的灾难字符串存储。
以下作品
int *day_tab[]= {
st,
st2
};
,因为当你访问一个数组时,它被转换为指向第一个元素的指针(对于这条规则有几个例外)。因此,当您初始化st
和st2
数组时,它们将转换为指向各自数组第一个元素的指针,初始化后,指针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',' '},
{'0','1',' '}
};
你试图用多个初始化器初始化数组day_tab
的指针。注意指针是标量类型和C11 Standard#6.7.9p11
11标量的初始化式必须是单个表达式,可选地用大括号括起来....
但是,您可以使用复合字面值来初始化day_tab
int
指针数组的指针,如下所示:
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',' '},
(char []){'0','1',' '}
};
当你这样做
char *day_tab[]= {
"01",
"01"
};
它工作是因为字符串字面量是字符数组,当它在表达式中使用时,它将转换为指向类型char
的指针,指向数组的第一个元素。因此,这将初始化指针day_tab[0]
和day_tab[1]
,使其指向只读的第一个元素。string literal"01"
.