C 复合文字、数组指针

发布于 2024-10-29 15:00:50 字数 605 浏览 3 评论 0原文

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

  int *p[] = (int *[]) {{1,2,3},{4,5,6}};

我在 gcc 中遇到错误。

但如果我只写这个:

  int p[] = (int []) {1,2,3,4,5,6};

那就没问题了。

但这不是我想要的。

我不明白为什么会发生错误,因为如果我像数组一样初始化它,或者将它与字符数组的指针一起使用,那就可以了,请参阅:

  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!

注意我不明白为什么我在第一个中出现错误,拜托,我不能,或者我不想像第二种形式那样写,因为它需要是复合文字,而且我不想告诉编译器数组有多大。我想要类似第二个的东西,但是对于 int 值。

提前致谢。

I'm trying to assign a compound literal to a variable, but it seems not to work, see:

  int *p[] = (int *[]) {{1,2,3},{4,5,6}};

I got a error in gcc.

but if I write only this:

  int p[] = (int []) {1,2,3,4,5,6};

Then it's okay.

But is not what I want.

I don't understand why the error occurrs, because if I initialize it like a array, or use it with a pointer of arrays of chars, its okay, see:

  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!

Note I don't understand why I got an error in the first one, and please I can't, or I don't want to write like the second form because it's needs to be a compound literals, and I don't want to say how big is the array to the compiler. I want something like the second one, but for int values.

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

╄→承喏 2024-11-05 15:00:50

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

  • 多维数组:

    int p[][3] = {{1,2,3},{4,5,6}};
    
  • 指向一维数组的指针数组:

    int p1[] = {1,2,3};
    int p2[] = {4,5,6};
    int *p[] = {p1,p2};
    

后一种方法的优点是允许不同长度的子数组。而前一种方法确保内存是连续布局的。

我强烈建议您不要使用的另一种方法是在字符串文字中对整数进行编码。这是一个不可移植的黑客。此外,字符串文字中的数据应该是常量。您的数组需要可变吗?

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"
};

该示例可能适用于 32 位小端机器,但我是从 iPad 上输入的,目前无法验证它。再次强调,请不要使用它;甚至提起这件事我都觉得很肮脏。

您发现的转换方法似乎也适用于指向指针的指针。它也可以像多维数组一样进行索引。

int **p = (int *[]) { (int[]) {1,2,3}, (int[]) {4,5,6} };

First, the casts are redundant in all of your examples and can be removed. Secondly, you are using the syntax for initializing a multidimensional array, and that requires the second dimension the be defined in order to allocate a sequential block of memory. Instead, try one of the two approaches below:

  • Multidimensional array:

    int p[][3] = {{1,2,3},{4,5,6}};
    
  • Array of pointers to one dimensional arrays:

    int p1[] = {1,2,3};
    int p2[] = {4,5,6};
    int *p[] = {p1,p2};
    

The latter method has the advantage of allowing for sub-arrays of varying length. Whereas, the former method ensures that the memory is laid out contiguously.

Another approach that I highly recommend that you do NOT use is to encode the integers in string literals. This is a non-portable hack. Also, the data in string literals is supposed to be constant. Do your arrays need to be mutable?

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"
};

That example might work on a 32-bit little-endian machine, but I'm typing this from an iPad and cannot verify it at the moment. Again, please don't use that; I feel dirty for even bringing it up.

The casting method you discovered also appears to work with a pointer to a pointer. That can be indexed like a multidimensional array as well.

int **p = (int *[]) { (int[]) {1,2,3}, (int[]) {4,5,6} };
紙鸢 2024-11-05 15:00:50

首先要理解“数组不是指针”。

int p[] = (int []) {1,2,3,4,5,6};

在上面的例子中,p是一个整数数组。将元素 {1,2,3,4,5,6} 复制到 p。这里不需要类型转换,rvaluelvalue 类型都匹配整数数组,因此不会出现错误。

int *p[] = (int *[]) {{1,2,3},{4,5,6}};

“请注意,我不明白为什么我在第一个错误中遇到错误,..”

在上面的情况下,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.

但是为什么这个语句会编译?

char *p[] = {"one", "two"...};

字符串文字与整数文字不同。在这种情况下,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.

对于字符串文字,上述任何一种情况都是可能的。这就是声明编制的原因。但 -

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.

我不想告诉编译器这个数组有多大。

使用malloc动态分配内存是解决方案。

希望有帮助!

First understand that "Arrays are not pointers".

int p[] = (int []) {1,2,3,4,5,6};

In the above case p is an array of integers. Copying the elements {1,2,3,4,5,6} to p. Typecasting is not necessary here and both the rvalue and lvalue types match which is an integer array and so no error.

int *p[] = (int *[]) {{1,2,3},{4,5,6}};

"Note I don't understand why I got a error in the first one,.."

In the above case, p an array of integer pointers. But the {{1,2,3},{4,5,6}} is a two dimensional array ( i.e., [][] ) and cannot be type casted to array of pointers. You need to initialize as -

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.

But why did this statement compile ?

char *p[] = {"one", "two"...};

String literals are different from integer literals. In this case also, p is an array of character pointers. When actually said "one", it can either be copied to an array or point to its location considering it as read only.

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.

With string literals, either of the above case is possible. So, that is the reason the statement compiled. But -

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.

I don't want to say how big is the array to the compiler.

Dynamically allocating the memory using malloc is the solution.

Hope it helps !

故乡的云 2024-11-05 15:00:50

既然没有人说过:如果你想要一个指向二维数组的指针,你可以(可能)做类似编辑:的事情

int (*p)[][3] = &(int[][3]) {{1,2,3},{4,5,6}};

获得指向其第一个元素的指针:

int (*p)[3] = (int[][3]) {{1,2,3},{4,5,6}};

,或者你可以通过以下方式 您的示例不起作用是因为 {{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'}< /code> 除非编译器在失去常量时不会抱怨太多。

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

与指针混淆的原因:

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

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

Since nobody's said it: If you want to have a pointer-to-2D-array, you can (probably) do something like

int (*p)[][3] = &(int[][3]) {{1,2,3},{4,5,6}};

EDIT: Or you can have a pointer to its first element via

int (*p)[3] = (int[][3]) {{1,2,3},{4,5,6}};

The reason why your example doesn't work is because {{1,2,3},{4,5,6}} is not a valid initializer for type int*[] (because {1,2,3} is not a valid initializer for int*). Note that it is not an int[2][3] — it's simply an invalid expression.

The reason why it works for strings is because "one" is a valid initializer for char[] and char[N] (for some N>3). As an expression, it's approximately equivalent to (const char[]){'o','n','e','\0'} except the compiler doesn't complain too much when it loses constness.

And yes, there's a big difference between an initializer and an expression. I'm pretty sure char s[] = (char[]){3,2,1,0}; is a compile error in C99 (and possibly C++ pre-0x). There are loads of other things too, but T foo = ...; is variable initialization, not assignment, even though they look similar. (They are especially different in C++, since the assignment operator is not called.)

And the reason for the confusion with pointers:

  • Type T[] is implicitly converted to type T* (a pointer to its first element) when necessary.
  • T arg1[] in a function argument list actually means T * arg1. You cannot pass an array to a function for Various Reasons. It is not possible. If you try, you are actually passing a pointer-to-array. (You can, however, pass a struct containing a fixed-size array to a function.)
  • They both can be dereferenced and subscripted with identical (I think) semantics.

EDIT: The observant might notice that my first example is roughly syntactically equivalent to int * p = &1;, which is invalid. This works in C99 because a compound literal inside a function "has automatic storage duration associated with the enclosing block" (ISO/IEC 9899:TC3).

陌路黄昏 2024-11-05 15:00:50

您正在使用的是 int 指针数组。您应该使用指向数组的指针:

int (*p)[] = (int *) {{1,2,3}, {4,5,6}}

查看this答案更多细节。

The one that you are using is array of int pointers. You should use pointer to array :

int (*p)[] = (int *) {{1,2,3}, {4,5,6}}

Look at this answer for more details.

烟酉 2024-11-05 15:00:50

看来你混淆了指针和数组。它们不是同一个东西!数组就是列表本身,而指针只是一个地址。然后,通过指针算术,您可以假装指针是数组,并且由于数组的名称是指向第一个元素的指针,所以一切都变得一团糟。 ;)

int *p[] = (int *[]) {{1,2,3},{4,5,6}};      //I got a error

这里,p 是一个指针数组,因此您尝试将地址为 1、2、3 的元素分配给第一个数组,将 4、5、6 分配给第二个数组。发生段错误是因为您无法访问这些内存位置。

int p[][3] = {{1,2,3},{4,5,6}};              //it's okay

这是可以的,因为这是一个数组的数组,所以这次 1、2、3、4、5 和 6 不是地址,而是元素本身。

char *p[] = (char *[]) {"one", "two"...};    // it's okay!

这是可以的,因为字符串文字(“one”,“two”,...)并不是真正的字符串,而是指向这些字符串的指针,因此您将字符串文字“one”的地址分配给 p[1] .
顺便说一句,这与执行 char abc[]; 相同。 abc = "abc";.这不会编译,因为你不能将指针分配给数组,而 char *def; def = "def"; 解决了这个问题。

It seems you are confusing pointers and array. They're not the same thing! An array is the list itself, while a pointer is just an address. Then, with pointer arithmetic you can pretend pointers are array, and with the fact that the name of an array is a pointer to the first element everything sums up in a mess. ;)

int *p[] = (int *[]) {{1,2,3},{4,5,6}};      //I got a error

Here, p is an array of pointers, so you are trying to assign the elements whose addresses are 1, 2, 3 to the first array and 4, 5, 6 to the second array. The seg fault happens because you can't access those memory locations.

int p[][3] = {{1,2,3},{4,5,6}};              //it's okay

This is ok because this is an array of arrays, so this time 1, 2, 3, 4, 5 and 6 aren't addresses but the elements themselves.

char *p[] = (char *[]) {"one", "two"...};    // it's okay!

This is ok because the string literals ("one", "two", ...) aren't really strings but pointers to those strings, so you're assigning to p[1] the address of the string literal "one".
BTW, this is the same as doing char abc[]; abc = "abc";. This won't compile, because you can't assign a pointer to an array, while char *def; def = "def"; solves the problem.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文