我试图刷我的C概念,现在它似乎都混乱了:(在指针,当然
这种将arr
分配给ptr
的方式是有效的,因为我们说arr[]
将衰变为*arr
int arr[] = {1, 2, 3};
int *ptr = arr; // Access arr with ptr
但是直接给*ptr
赋值是不行的
int *ptr = {1, 2, 3};
printf("%dn", ptr[0]); // Segmentation fault
我的理解是int arr[] = {}
有一个特殊的含义,在那里分配了一个连续的堆栈空间块,并直接通过名称arr
引用。试图做同样的事情与int *ptr = {}
只是混淆编译器??
变量ptr
是一个标量对象。可以使用只包含一个表达式的带括号的列表初始化标量对象。
来自C标准(6.7.9 Initialization)
11标量的初始化式必须是单个表达式;可选地用大括号括起来。对象的初始值为表达式的值(转换后);相同类型的约束和简单赋值的转换一样适用,取的类型标量为其声明类型的非限定版本。
所以不是:
int *ptr = {1, 2, 3};
你可以这样写:
int *ptr = { 3 };
等于:
int *ptr = 3;
和没有意义,编译器可以发出消息,将整数转换为指针,而不需要强制转换。
可以用复合字面值来初始化指针,如:
int *ptr = ( int [] ){1, 2, 3};
在此声明中,创建了一个未命名的类型为int[3]
的数组,并将该数组的第一个元素的地址赋给指针。
{1, 2, 3}
不代表"数组"。在声明中,它是一个包含多个部分的对象的初始值列表。
在int arr[] = {1, 2, 3};
中,{1, 2, 3}
是一个包含三个值的列表,用于初始化数组arr
。
在int *ptr = {1, 2, 3};
中,{1, 2, 3}
将是一个包含三个值的列表,用于初始化指针ptr
。但是ptr
没有多个部分。它只有一个值,一个内存地址。因此,{1, 2, 3}
将提供1
来初始化地址,这是一个问题,因为1
是int
,而不是地址,因此编译器应该为此发出诊断消息。并且2
或3
没有什么可初始化的,因此编译器应该为此发出诊断消息。
您可以使用复合文字直接在源代码中创建未命名的数组。复合字面值的形式为(type) {initial values}
。所以你可以用(int []) {1, 2, 3}
创建一个int
的数组。
可以声明一个指针,并使用复合字面值作为初始值将其初始化为指向数组的指针:
int *ptr = (int []) {1, 2, 3};
(注意数组会自动转换为指向第一个元素的指针,因此ptr
初始化为该地址)