C复合文字,指向数组的指针

dri*_*ker 31 c compound-literals

我正在尝试将复合文字分配给变量,但似乎不起作用,请参阅:

  int *p[] = (int *[]) {{1,2,3},{4,5,6}};
Run Code Online (Sandbox Code Playgroud)

我在gcc中遇到错误.

但如果我只写这个:

  int p[] = (int []) {1,2,3,4,5,6};
Run Code Online (Sandbox Code Playgroud)

那没关系.

但这不是我想要的.

我不明白为什么错误发生,因为如果我像数组一样初始化它,或者使用字符数组的指针,它没关系,请参阅:

  int *p[] = (int *[]) {{1,2,3},{4,5,6}}; //I got a error
  int p[][3] = {{1,2,3},{4,5,6}}; //it's okay
  char *p[] = (char *[]) {"one", "two"...}; // it's okay!
Run Code Online (Sandbox Code Playgroud)

注意我不明白为什么我在第一个错误中得到错误,请我不能,或者我不想写第二个表单,因为它需要是复合文字,我不想要说数组到编译器有多大.我想要第二个,但是对于int值.

提前致谢.

Jud*_*den 31

首先,在所有示例中,强制转换都是多余的,可以删除.其次,您使用语法初始化多维数组,并且需要定义第二个维度以分配顺序内存块.相反,请尝试以下两种方法之一:

后一种方法具有允许不同长度的子阵列的优点.然而,前一种方法确保存储器连续布局.

我强烈建议您不要使用的另一种方法是在字符串文字中编码整数.这是一个非便携式黑客.此外,字符串文字中的数据应该是常量.你的阵列需要是可变的吗?

int *p[] = (int *[]) {
    "\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00",
    "\x04\x00\x00\x00\x05\x00\x00\x00\x06\x00\x00\x00"
};
Run Code Online (Sandbox Code Playgroud)

这个例子可能适用于32位小端机器,但是我在iPad上输入此内容并且目前无法验证它.再次,请不要使用它; 甚至提起它我都觉得很脏.

您发现的转换方法似乎也可以使用指向指针的指针.它也可以像多维数组一样被索引.

int **p = (int *[]) { (int[]) {1,2,3}, (int[]) {4,5,6} };
Run Code Online (Sandbox Code Playgroud)

  • `()`中的类型不是强制转换 - 它是复合文字语法的一部分. (7认同)

Mah*_*esh 13

首先要明白"数组不是指针".

int p[] = (int []) {1,2,3,4,5,6};
Run Code Online (Sandbox Code Playgroud)

在上面的例子中p是一个整数数组.将元素复制{1,2,3,4,5,6}p.类型转换在这里没有必要并且两个rvaluelvalue类型匹配这是一个整数阵列等没有错误.

int *p[] = (int *[]) {{1,2,3},{4,5,6}};
Run Code Online (Sandbox Code Playgroud)

"注意我不明白为什么我在第一个错误中出现错误,......"

在上面的例子中,p是一个整数指针数组.但它{{1,2,3},{4,5,6}}是一个二维数组(即[] []),不能被类型转换为指针数组.你需要初始化为 -

int p[][3] = { {1,2,3},{4,5,6} };
  // ^^ First index of array is optional because with each column having 3 elements
  // it is obvious that array has two rows which compiler can figure out.
Run Code Online (Sandbox Code Playgroud)

但为什么这个陈述会编译?

char *p[] = {"one", "two"...};
Run Code Online (Sandbox Code Playgroud)

字符串文字与整数文字不同.在这种情况下,p也是一个字符指针数组.实际上说"one",它可以被复制到一个数组或指向它的位置,将其视为只读.

char cpy[] = "one" ;
cpy[0] = 't' ;  // Not a problem

char *readOnly = "one" ;
readOnly[0] = 't' ;  // Error because of copy of it is not made but pointing
                     // to a read only location.
Run Code Online (Sandbox Code Playgroud)

使用字符串文字,上述任何一种情况都是可能的.所以,这就是声明编写的原因.但是 -

char *p[] = {"one", "two"...}; // All the string literals are stored in 
                               // read only locations and at each of the array index 
                               // stores the starting index of each string literal.
Run Code Online (Sandbox Code Playgroud)

我不想说数组对编译器有多大.

动态分配内存malloc是解决方案.

希望能帮助到你 !

  • 仅仅因为一维数组可能并不意味着**数组是一个指针**. (3认同)
  • 区别之一是您无法更改数组的地址,但您可以为指针执行此操作.因此,您可以调用数组`静态地址`和指针 - 动态地址`. (2认同)

tc.*_*tc. 5

因为没有人说过:如果你想要一个指向2D数组的指针,你可以(可能)做类似的事情

int (*p)[][3] = &(int[][3]) {{1,2,3},{4,5,6}};
Run Code Online (Sandbox Code Playgroud)

编辑:或者你可以有一个指向其第一个元素的指针

int (*p)[3] = (int[][3]) {{1,2,3},{4,5,6}};
Run Code Online (Sandbox Code Playgroud)

您的示例不起作用的原因是因为{{1,2,3},{4,5,6}}它不是类型的有效初始值设定项int*[](因为{1,2,3}它不是有效的初始值设定项int*).请注意,这是不是一个int[2][3]-它只是一个无效的表达.

为什么它的字符串的原因是因为"one"是一个有效的初始化char[]char[N](对于一些N> 3).作为一个表达式,它大致相当于(const char[]){'o','n','e','\0'}除了编译器在失去constness时不会抱怨太多.

是的,初始化器和表达式之间存在很大差异.我很确定char s[] = (char[]){3,2,1,0};C99中的编译错误(可能是C++前置0x).还有许多其他的东西,但是T foo = ...;变量初始化,而不是赋值,即使它们看起来相似.(它们在C++中特别不同,因为不调用赋值运算符.)

与指针混淆的原因:

  • 必要时,Type T[]会隐式转换为type T*(指向其第一个元素的指针).
  • T arg1[]在函数参数列表中实际意味着T * arg1.您无法将数组传递给各种原因的函数.这不可能.如果你尝试,你实际上是传递一个指向数组的指针.(但是,您可以将包含固定大小数组的结构传递给函数.)
  • 它们都可以被解除引用并使用相同的(我认为)语义进行下标.

编辑:观察者可能会注意到我的第一个例子大致在语法上等同于int * p = &1;,这是无效的.这适用于C99,因为函数内的复合文字"具有与封闭块相关联的自动存储持续时间"(ISO/IEC 9899:TC3).