简体   繁体   English

使用指针初始化const数组

[英]Initialize a const array with a pointer

Why is the first line valid but the rest invalid. 为什么第一行有效但其余行无效。 I though the first was a shorthand for the second. 我虽然第一个是第二个的速记。

const char *c = "abc"; // Why valid?

const char *b = { 'a' , 'b', 'c', '\0' }; // invalid

const int *a = { 1, 2, 3, 0 }; // invalid

The real difference here is that "abc" is a string literal of type char[] , whereas {'a', 'b', 'c', 0} is not. 这里真正的区别是"abc"char[]类型的字符串文字,而{'a', 'b', 'c', 0}则不是。 You could easily use it to initialize a completely different type, for example: 您可以轻松地使用它来初始化完全不同的类型,例如:

struct s{
  char c;
  int i, j;
  float f;
} x = {'a', 'b', 'c', 0};

So when you write const char *b = { 'a' , 'b', 'c', '\\0' }; 所以当你写const char *b = { 'a' , 'b', 'c', '\\0' }; , the compiler picks the implicit conversion {'a'} -> 'a' and tries to initialize your pointer with that. ,编译器选择隐式转换{'a'} -> 'a'并尝试用它初始化你的指针。 This may or may not fail depending on the compiler and the actual value, for example many compilers would interpret const char *b = { '\\0' }; 根据编译器和实际值,这可能会也可能不会失败,例如,许多编译器会解释const char *b = { '\\0' }; as initializing b to a NULL pointer instead of an empty string as one could expect. b初始化为NULL指针而不是像预期的那样将空字符串初始化。

If you want to initialize the pointer to the address of an array (or any other type) created with list initialization, you should cast explicitly: 如果要初始化指向使用列表初始化创建的数组(或任何其他类型)的地址的指针,则应显式转换:

const char *b = (const char[]){'a', 'b', 'c', 0};
const int *a = (const int[]){'a', 'b', 'c', 0};
struct s *x = &(struct s){'a', 'b', 'c', 0};

In the first case you have a string literal which are arrays of char, it will be converted to a pointer to char in this context. 在第一种情况下,您有一个字符串文字,它是char数组,在此上下文中它将转换为指向char的指针。

In the next two cases you are attempting to use list initialization to initialize a pointer which will attempt to convert the first element of the list to a pointer which generates a warning since neither a char or an int are pointers, the same way this would: 在接下来的两种情况下,您尝试使用列表初始化来初始化一个指针,该指针将尝试将列表的第一个元素转换为生成警告的指针,因为char或int都不是指针,这与以下方式相同:

const char *b = 'a' ;

If you had valid pointers in the list it would work fine for the first element but would be ill-formed since you have more initializers than variables. 如果列表中有有效的指针,它对第一个元素可以正常工作,但由于你有更多的初始值而不是变量,因此格式不正确。

Array and pointer isn't the same thing. 数组和指针不是一回事。

const char *c = "abc";

Initialise pointer with address of string constant. 初始化带有字符串常量地址的指针。 Sting constant contained elsewhere (not on stack, usually special global constant area). Sting常量包含在其他地方(不在堆栈上,通常是特殊的全局常量区域)。

const char c[] = "abc";

Initialise array of chars with given characters (with contents of given string). 初始化具有给定字符的chars数组(具有给定字符串的内容)。 This one would be on stack. 这个将在堆栈上。

The first line is valid because the C standard allows for the creation of constant strings, because their length can be determined at compile time. 第一行是有效的,因为C标准允许创建常量字符串,因为它们的长度可以在编译时确定。

The same does not apply to pointers: the compiler can't decide whether it should allocate the memory for the array in the heap (just like a normal int[] , for instance) or in regular memory, as in malloc() . 这同样不适用于指针:编译器无法决定是否应该为堆中的数组(例如,正常的int [] )或常规内存中分配内存,如malloc()

If you initialize the array as: 如果将阵列初始化为:

   int a[] = { 1, 2, 3, 0 };

then it becomes valid, because now the compiler is sure that you want an array in the heap (temporary) memory, and it will be freed from memory after you leave the code section on which this is declared. 然后它变得有效,因为现在编译器确定你想在堆(临时)内存中有一个数组,并且在你离开声明它的代码部分后它将从内存中释放出来。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM