143

我不确定通过以下方式初始化后 char 数组中的内容。

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

对于案例 2,我认为buf[0]should be ' 'buf[1]should be'\0'和 from buf[2]tobuf[9]将是随机内容。对于案例 3,我认为buf[0]应该是'a'buf[1]应该是 '\0',并且 from buf[2]tobuf[9]将是随机内容。

那是对的吗?

对于案例 1,将是什么bufbuf[0] == '\0'from buf[1]tobuf[9]将是随机内容吗?

4

6 回答 6

253

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

  1. 第一个声明:

    char buf[10] = "";
    

    相当于

    char buf[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
  2. 第二个声明:

    char buf[10] = " ";
    

    相当于

    char buf[10] = {' ', 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
  3. 第三个声明:

    char buf[10] = "a";
    

    相当于

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

如您所见,没有随机内容:如果初始化程序较少,则数组的剩余部分使用0. 即使在函数内部声明数组也是如此。

于 2013-09-08T21:51:22.650 回答
36
  1. 这些是等价的

    char buf[10] = "";
    char buf[10] = {0};
    char buf[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
  2. 这些是等价的

    char buf[10] = " ";
    char buf[10] = {' '};
    char buf[10] = {' ', 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
  3. 这些是等价的

    char buf[10] = "a";
    char buf[10] = {'a'};
    char buf[10] = {'a', 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
于 2014-09-29T16:15:36.927 回答
30

编辑:在我提供此答案后,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];

您将在所有元素中包含随机内容。

于 2013-09-08T22:20:20.907 回答
12

C11 标准草案 n1570 6.7.9 初始化的相关部分说:

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

21 如果大括号括起来的列表中的初始值设定项少于聚合的元素或成员,或者用于初始化已知大小数组的字符串文字中的字符少于数组中的元素,则聚合的剩余部分应隐式初始化与具有静态存储持续时间的对象相同。

因此,如果有足够的空间,则附加 '\0',并且使用将在函数中初始化 a 的值来初始化剩余的字符static char c;

最后,

10 如果具有自动存储持续时间的对象未显式初始化,则其值是不确定的。如果具有静态或线程存储持续时间的对象未显式初始化,则:

[--]

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

[--]

因此,char作为算术类型,数组的其余部分也保证用零初始化。

于 2016-07-05T11:03:47.530 回答
3

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

示例程序:

#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;
}
于 2014-05-13T10:51:07.063 回答
1

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

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'
}
于 2016-04-01T01:41:58.557 回答