字符数组初始化

我不确定在以下方式初始化之后 char 数组中会有什么内容。

1. char buf[10] = "";
2. char buf[10] = " ";
3. char buf[10] = "a";

对于情况2,我认为 buf[0]应该是 ' 'buf[1]应该是 '\0',从 buf[2]buf[9]将是随机的内容。对于情况3,我认为 buf[0]应该是 'a'buf[1]应该是’0’,从 buf[2]buf[9]将是随机的内容。

是这样吗?

对于情况1,在 buf中是什么?buf[0] == '\0'和从 buf[1]buf[9]会是随机的内容吗?

756914 次浏览

这不是初始化数组的方式,而是用于:

  1. 第一个声明:

    char buf[10] = "";
    

    相当于

    char buf[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
  2. The second declaration:

    char buf[10] = " ";
    

    相当于

    char buf[10] = {' ', 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
  3. The third declaration:

    char buf[10] = "a";
    

    相当于

    char buf[10] = {'a', 0, 0, 0, 0, 0, 0, 0, 0, 0};
    

As you can see, no random content: if there are fewer initializers, the remaining of the array is initialized with 0. This the case even if the array is declared inside a function.

编辑: OP (或编辑器)在我给出这个答案之后,默默地将原问题中的一些单引号改为双引号。

您的代码将导致编译器错误。第一个代码片段:

char buf[10] ; buf = ''

是双重违法的。首先,在 C 语言中,没有空 char这种东西。可以使用双引号来指定空字符串,如下所示:

char* buf = "";

这将为您提供一个指向 NUL字符串的指针,即一个只包含 NUL字符的单字符串。但是不能使用没有任何内容的单引号——这是未定义的。如果需要指定 NUL字符,则必须指定它:

char buf = '\0';

反斜杠是消除字符 '0'的歧义所必需的。

char buf = 0;

完成同样的事情,但是我认为前者读起来没有那么模棱两可。

其次,不能在定义数组之后初始化它们。

char buf[10];

声明并定义数组。数组标识符 buf现在是内存中的一个地址,您不能通过赋值更改 buf指向的位置。那么

buf =     // anything on RHS

是非法的。因为这个原因,您的第二和第三个代码片段是非法的。

要初始化一个数组,必须在定义时进行:

char buf [10] = ' ';

将给出一个10个字符的数组,其中第一个字符是空间 '\040',其余字符是 NUL,即 '\0'。当使用初始值设定项声明和定义阵列时,阵列元素(如果有的话)会自动用 0填充。不会有任何“随机内容”。

如果声明和定义数组但不初始化它,如下所示:

char buf [10];

在所有元素中都会有随机的内容。

有趣的是,只要数组是 structunion的成员,就可以在程序的任何时候以任何方式初始化数组。

示例程序:

#include <stdio.h>


struct ccont
{
char array[32];
};


struct icont
{
int array[32];
};


int main()
{
int  cnt;
char carray[32] = { 'A', 66, 6*11+1 };    // 'A', 'B', 'C', '\0', '\0', ...
int  iarray[32] = { 67, 42, 25 };


struct ccont cc = { 0 };
struct icont ic = { 0 };


/*  these don't work
carray = { [0]=1 };           // expected expression before '{' token
carray = { [0 ... 31]=1 };    // (likewise)
carray = (char[32]){ [0]=3 }; // incompatible types when assigning to type 'char[32]' from type 'char *'
iarray = (int[32]){ 1 };      // (likewise, but s/char/int/g)
*/


// but these perfectly work...
cc = (struct ccont){ .array='a' };        // 'a', '\0', '\0', '\0', ...
// the following is a gcc extension,
cc = (struct ccont){ .array={ [0 ... 2]='a' } };  // 'a', 'a', 'a', '\0', '\0', ...
ic = (struct icont){ .array={ 42,67 } };      // 42, 67, 0, 0, 0, ...
// index ranges can overlap, the latter override the former
// (no compiler warning with -Wall -Wextra)
ic = (struct icont){ .array={ [0 ... 1]=42, [1 ... 2]=67 } }; // 42, 67, 67, 0, 0, ...


for (cnt=0; cnt<5; cnt++)
printf("%2d %c %2d %c\n",iarray[cnt], carray[cnt],ic.array[cnt],cc.array[cnt]);


return 0;
}
  1. 这些是等价的

    char buf[10] = "";
    char buf[10] = {0};
    char buf[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
  2. These are equivalent

    char buf[10] = " ";
    char buf[10] = {' '};
    char buf[10] = {' ', 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
  3. These are equivalent

    char buf[10] = "a";
    char buf[10] = {'a'};
    char buf[10] = {'a', 0, 0, 0, 0, 0, 0, 0, 0, 0};
    

我不确定,但我通常将数组初始化为“” 在这种情况下,我不需要担心字符串的空端。

main() {
void something(char[]);
char s[100] = "";


something(s);
printf("%s", s);
}


void something(char s[]) {
// ... do something, pass the output to s
// no need to add s[i] = '\0'; because all unused slot is already set to '\0'
}

C11标准草案 n15706.7.9初始化的相关部分说明:

字符类型的数组可以用字符串文字或 UTF-8字符串初始化 字符串的连续字节(包括 如果有空间或数组大小未知,则终止空字符)初始化 数组的元素。

还有

在括号内的列表中,如果有的话初始值设定项比元素或成员少 或者 < strong > 字符串文字中的较少字符,用于初始化已知的 大于数组中的元素,则聚合的其余部分应为 隐式初始化与具有 静态存储时间静态存储时间。

的对象相同

因此,’0’被追加,如果有足够的空间,其余的字符被初始化,static char c;将在一个函数中被初始化。

终于,

如果没有显式初始化具有自动存储持续时间的对象,则其值为 不确定。如果没有初始化具有 静电干扰或线程存储持续时间的对象 那么,明确地说:

[--]

  • 如果它具有算术类型,则将其初始化为(正或无符号)零;

[--]

因此,char是一种算术类型,数组的其余部分也保证用零进行初始化。