指针声明数组

时间:2015-12-04 11:45:37

标签: c arrays pointers

我需要对指针数组进行一些解释,更准确,如何声明它们
看看这段代码:

main()
{
    int array[] = {5, 4, 2};
    int array2[] = {6, 8};
    int* int_arrays[2] = {array, array2}; // It works!

//  int* int_arrays2[2] =
//  {
//      {5, 4, 2},
//      {6, 8}
//  };
//
    int i, j;
    for(i = 0; i < 2; i++) 
    {
        for(j = 0; j < 3; j++) // This loop print a garbage value at the end, no big deal.
                printf("%d\n", int_arrays[i][j]);
    }
}

对我来说,评论的声明与上面的声明相同。但它不起作用。
Visual Studio C编译器给我这些指示:
错误:初始化程序太多。
警告:int *与int的间接级别不同。

我想这意味着int array[] = {5, 4, 2}是有效分配给int*的东西 虽然{5, 4, 2}不是。{ 你能告诉我一种方法来正确识别我的指针数组吗?

3 个答案:

答案 0 :(得分:5)

数组初始值设定项不是对象,因此您无法指向此类对象的开头。如果你有至少C99,你可以做

int* int_arrays2[2] =
{
     (int[]){5, 4, 2},
     (int[]){6, 8}
};

这些是所谓的&#34;复合文字&#34;它们是对象,因此在这种情况下会转换为您需要的指针类型。

答案 1 :(得分:3)

声明

int* int_arrays[2]

将变量int_arrays声明为两个指向int的指针的数组。并且您初始化数组以在&#34中包含两个指向int的指针;它可以正常工作&#34;码。请记住,数组会自然地衰减到指向第一个元素的指针,例如,int数组可以在预期int *的位置使用。

但是,您不能使用数组初始值设定项列表(如{ 5, 4, 2})作为指针,因为它不是。这就是为什么您注释掉的代码无法构建的原因。您可以在声明时使用数组数组,因为这是您初始化它的方式:

char int_array_of_arrays[2][3] = { ... };

重要的不是数组数组,而是数组到指针的衰减:An array of arrays is not the same as a pointer to pointer

至于&#34;垃圾&#34;问题,这是因为你试图打印只包含两个元素的数组的第三个元素。 C没有任何边界检查,如果你试图将一个数组索引越界,你将有未定义的行为

答案 2 :(得分:2)

考虑第一个声明

int* int_arrays[2] = {array, array2}; 

这是initilaizer列表包含两个表示数组名称的表达式。表达式中使用的数组被隐式转换为指向其第一个元素的指针。

事实上,这个声明等同于以下

int* int_arrays[2] = { &array[0], &array2[0] };

考虑到int_arrays被声明为具有两个元素的数组,因此使用两个初始值设定项来初始化数组的元素。

您可以将初始化程序列表与多个初始化程序一起使用来初始化聚合:数组和结构。

如果使用标量值,则相应的初始化列表可能只有一个初始值设定项。考虑

int x = { 10 };  // Okey
int y = ( 10, 20 }; // compiler error

现在考虑一下这个宣言

int* int_arrays2[2] =
{
      {5, 4, 2},
      {6, 8}
};

在此声明中,数组int_arrays2与以前一样只包含两个元素。数组的每个元素都是int *类型的标量对象。初始化在语义上等同于以下

int *p1 = {5, 4, 2};
int *p2 = {6, 8};

其中p1p2对应int_arrays2[0]int_arrays2[1]

它们是标量对象,正如上面所指出的那样,只能通过带有一个初始值设定项的初始化列表初始化。

因此编译器会发出错误。

另一方面,你可以写

而不是这个错误的声明
int* int_arrays2[2] =
{
      ( int[] ){5, 4, 2},
      ( int [] ){6, 8}
};

这里使用了所谓的复合文字,它可以创建指定类型的未命名数组。因此在左侧有一个包含两个元素的数组,在右侧有一个初始化列表,其中包含两个初始化器,复合文字,转换为指向创建的未命名数组的第一个元素的指针。

这样的初始化是正确的。