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



我明白如果我添加数组,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
};

,因为当你访问一个数组时,它被转换为指向第一个元素的指针(对于这条规则有几个例外)。因此,当您初始化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',''},
{'0','1',''}
};

你试图用多个初始化器初始化数组day_tab的指针。注意指针是标量类型和C11 Standard#6.7.9p11

11标量的初始化式必须是单个表达式,可选地用大括号括起来....

但是,您可以使用复合字面值来初始化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',''},
(char []){'0','1',''}
};

当你这样做

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

它工作是因为字符串字面量是字符数组,当它在表达式中使用时,它将转换为指向类型char的指针,指向数组的第一个元素。因此,这将初始化指针day_tab[0]day_tab[1],使其指向只读的第一个元素。string literal"01".

最新更新