2015-12-04 150 views
4

我需要一些关于指针数组的解释和更精确的如何声明它们
看看这个代码:
数组指针声明

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]); 
    } 
} 

对我的评论declartation意思一样,如上图所示。但它不起作用。
Visual Studio C编译器给我提供了这些指示:
错误:太多初始值设定项。
警告:int *与int的间接级别不同。

我想这意味着int array[] = {5, 4, 2}东西有效的分配到int*
{5, 4, 2}不是。
您能否告诉我一种正确删除指针数组的方法?

回答

5

数组初始化是不是一个对象,所以你不能有一个指针的这样和对象的开始。如果您有至少C99,你可以做

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

这些所谓的“复合文字”是对象,因此在这种情况下,隐蔽到你需要的指针类型。

+0

伟大的答案,它是在你的未来的书.. – artm

+0

这很有趣,因为在发布我的问题之前,我尝试的最后一件事是将数组初始化器投射到'(int *)'。我猜'(int [])'工作,因为初始化器被转换为一个数组,然后'array [0]'自然等价于'* array'? – aurelienC

+0

@atm,是的,复合文字开始于第5.4.4节或“现代C” –

3

声明

int* int_arrays[2] 

声明变量int_arrays是两个指针数组以int。你初始化数组包含两个指向“it works”代码的int指针。请记住,阵列自然衰变到指针到他们的第一元件,因此,例如,可以使用其中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


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

+0

**请记住,数组自然衰减到指向他们的第一个元素的指针** bravo,这太棒了@JoachimPileborg +1 – Cherubim

+0

@ ch3rub7;不总是。我认为约阿希姆应该在他的回答中提到这一点。 – haccks

+0

数组数组的东西是所有的数组都有相同的长度,我想我可以用空值填充更小的数组......但无论如何,这只是一个理论问题。 “你不能使用数组初始值设定项列表(如{5,4,2})作为指针,因为它没有”澄清我的问题,谢谢! – aurelienC

2

考虑第一个声明

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

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

事实上这声明等效于以下

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

要考虑到int_arrays被声明为与两个元件,因此2个初始化用于初始化所述阵列的所述元件的阵列。

您可以使用具有多个初始化程序的初始化程序列表初始化聚合:数组和结构。

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

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

p1哪里和p2初始化avove对应int_arrays2[0]int_arrays2[1]

它们是标量对象,正如上面已经指出的,它可能只通过具有一个初始化器的初始化器列表进行初始化。

所以编译器发出错误。

在另一方面,而不是这种错误的声明,你可以写

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

这里使用的是创建指定类型的数组无名所谓复合文字。所以在左侧有一个由两个元素组成的数组,在右侧有一个初始化器列表,其中有两个初始化器,即复合文字,它们被转换为指向创建的未命名数组的第一个元素的指针。

这样的初始化是正确的。