C char数组v C char*初始化

时间:2022-09-06 10:53:22

The following is accepted as valid c code by gcc version 6.3:

gcc 6.3版本接受以下为有效的c代码:

char white[] = { 'a', 'b', 'c' };
char blue[]  = "abc";
char *red    = "abc";

However the following fails:

然而以下失败:

 char *green = { 'a', 'b', 'c' };   // gcc error

I am sure there is a perfectly rational reason for this to be the case, but I am wondering what it is. This question is motivated by the case when having to initialize an array of bytes (so unsigned char rather than char), it is very tempting to write something like { '\x43', '\xde', '\xa0' } rather than "\x43\xde\xa0", and as soon as you forget to write my_array[] instead of *my_array, you get caught by the compiler.

我确信有一个完全合理的理由可以解释这种情况,但我想知道它是什么。问题是出于这种情况时要初始化的字节数组(无符号字符而不是字符),很容易写类似{‘\ x43’,‘\ xde’,‘\ xa0 }而不是“\ x43 \ xde \ xa0”,一旦你忘记写my_array[]* my_array,相反,你会被编译器。

2 个解决方案

#1


7  

The following will produce an error

下面将产生一个错误

char *green = { 'a', 'b', 'c' };

Because the initializer for green isn't an array of characters as you believe. It doesn't have a type, it's just a brace-enclosed initializer list. The thing that it initializes in the previous samples (i.e. white) determines how it's interpreted. The same initialzier can be used to initialize any aggregate that is capable of holding 3 characters.

因为绿色的初始化器并不是你认为的字符数组。它没有类型,它只是一个括起来的初始化列表。在前面的示例中初始化的东西(即白色)决定了如何解释它。可以使用相同的initialzier初始化任何能够容纳3个字符的聚合。

But green is a pointer, and not an aggregate, so you can't use a brace-enclosed initializer list as it's initial value.1

但绿色是一个指针,而不是聚合,所以不能使用带括号的初始值设定项列表

Now, the following two work but with very different semantics:

下面这两项工作的语义非常不同:

char blue[]  = "abc";
char *red    = "abc";

blue is an array. It will hold the same contents as the literal "abc". red is a pointer that points at the literal "abc".

蓝色是一个数组。它将包含与字面“abc”相同的内容。红色是指向字母“abc”的指针。


  1. You can use a compound literal expression:

    你可以使用复合文字表达:

    char *green = (char[]){ 'a', 'b', 'c' };
    

    It tells the compiler to create an unnamed object (the life time of which depends on the scope of the declaration), that is of character array type and is initialized with those three characters. The pointer is then assigned the address of that object.

    它告诉编译器创建一个未命名对象(其生命周期取决于声明的范围),该对象是字符数组类型的,并使用这三个字符初始化。然后将该指针分配给该对象的地址。

#2


5  

These three declarations

这三个声明

char white[] = { 'a', 'b', 'c' };
char blue[]  = "abc";
char *red    = "abc";

are different.

是不同的。

The first one declares a character array that contains exactly three characters corresponding to the number of the initializers.

第一个声明了一个字符数组,该数组包含与初始化器的数量对应的三个字符。

The second one declares a character array of four characters because it is initialized by a string literal that has four characters including the terminating zero. So this character array contains a string.

第二个声明一个包含四个字符的字符数组,因为它是由一个包含四个字符(包括终止零)的字符串文字初始化的。这个字符数组包含一个字符串。

The third one defined a string literal that is a character array and declares a pointer of type char * that is initialized by the address of the first character of the character array corresponding to the string literal.

第三个定义了一个字符串字面值,它是一个字符数组,并声明了一个char *类型的指针,该指针由字符串字面值对应的字符数组的第一个字符的地址初始化。

You can imagine this declaration like

你可以把这个宣言想象成

char unnamed = { 'a', 'b', 'c', '\0' };
char *red = unnamed;

This declaration

这个声明

char *green = { 'a', 'b', 'c' };   

is invalid because the left object is a scalar and may not be initialized by a list that contains more than one initializer.

是无效的,因为左边的对象是一个标量,并且可能不会被包含多个初始化器的列表初始化。

Take into account that you could use a compound literal to initialize the pointer. For example

考虑到可以使用复合文字来初始化指针。例如

char *green = ( char[] ){ 'a', 'b', 'c' };   

#1


7  

The following will produce an error

下面将产生一个错误

char *green = { 'a', 'b', 'c' };

Because the initializer for green isn't an array of characters as you believe. It doesn't have a type, it's just a brace-enclosed initializer list. The thing that it initializes in the previous samples (i.e. white) determines how it's interpreted. The same initialzier can be used to initialize any aggregate that is capable of holding 3 characters.

因为绿色的初始化器并不是你认为的字符数组。它没有类型,它只是一个括起来的初始化列表。在前面的示例中初始化的东西(即白色)决定了如何解释它。可以使用相同的initialzier初始化任何能够容纳3个字符的聚合。

But green is a pointer, and not an aggregate, so you can't use a brace-enclosed initializer list as it's initial value.1

但绿色是一个指针,而不是聚合,所以不能使用带括号的初始值设定项列表

Now, the following two work but with very different semantics:

下面这两项工作的语义非常不同:

char blue[]  = "abc";
char *red    = "abc";

blue is an array. It will hold the same contents as the literal "abc". red is a pointer that points at the literal "abc".

蓝色是一个数组。它将包含与字面“abc”相同的内容。红色是指向字母“abc”的指针。


  1. You can use a compound literal expression:

    你可以使用复合文字表达:

    char *green = (char[]){ 'a', 'b', 'c' };
    

    It tells the compiler to create an unnamed object (the life time of which depends on the scope of the declaration), that is of character array type and is initialized with those three characters. The pointer is then assigned the address of that object.

    它告诉编译器创建一个未命名对象(其生命周期取决于声明的范围),该对象是字符数组类型的,并使用这三个字符初始化。然后将该指针分配给该对象的地址。

#2


5  

These three declarations

这三个声明

char white[] = { 'a', 'b', 'c' };
char blue[]  = "abc";
char *red    = "abc";

are different.

是不同的。

The first one declares a character array that contains exactly three characters corresponding to the number of the initializers.

第一个声明了一个字符数组,该数组包含与初始化器的数量对应的三个字符。

The second one declares a character array of four characters because it is initialized by a string literal that has four characters including the terminating zero. So this character array contains a string.

第二个声明一个包含四个字符的字符数组,因为它是由一个包含四个字符(包括终止零)的字符串文字初始化的。这个字符数组包含一个字符串。

The third one defined a string literal that is a character array and declares a pointer of type char * that is initialized by the address of the first character of the character array corresponding to the string literal.

第三个定义了一个字符串字面值,它是一个字符数组,并声明了一个char *类型的指针,该指针由字符串字面值对应的字符数组的第一个字符的地址初始化。

You can imagine this declaration like

你可以把这个宣言想象成

char unnamed = { 'a', 'b', 'c', '\0' };
char *red = unnamed;

This declaration

这个声明

char *green = { 'a', 'b', 'c' };   

is invalid because the left object is a scalar and may not be initialized by a list that contains more than one initializer.

是无效的,因为左边的对象是一个标量,并且可能不会被包含多个初始化器的列表初始化。

Take into account that you could use a compound literal to initialize the pointer. For example

考虑到可以使用复合文字来初始化指针。例如

char *green = ( char[] ){ 'a', 'b', 'c' };