我有一个指向数组(二维数组)的指针。我喜欢将二维数组分配给一个指针
int (*p)[2]={{1,2}};//SegFault
int (*p)[2]=(int **){{1,2},{3,4}}; //should it be same as above? but also causing segFault/
int (*p)[2]=(int[][]){{5,4},{5,6}};//should it be same as above two? but also causing segFault
以及如何访问这些值。访问第一个数组和第一个值是否正确 *(*(p)
。 // 它是否也有效 p[0][0]
我认为是这样,但请澄清这些访问方法纯粹是 C 的设计方式,或者如果我使用 *(*(p))
或 p[0][0]
< /p>
答案 0 :(得分:2)
本声明
int (*p)[2]={{1,2}};
在语法上不正确。指针是标量对象,它们可以由一个可选地括在大括号中的表达式初始化。
在本声明中
int (*p)[2]=(int **){{1,2},{3,4}}
您正在尝试使用复合文字,但再次初始化不正确,因为 int **
类型的对象是标量对象,并且我可以通过单个表达式进行初始化。
在这个带有复合字面量的声明中
int (*p)[2]=(int[][]){{5,4},{5,6}};
二维数组使用了不正确的类型说明符 int[][]
,因为数组元素的大小未知。你可以写例如
int (*p)[2]=(int[][2]){{5,4},{5,6}};
也就是说,您需要有一个将分配给指针的数组。如果您没有这样的数组,则可以使用复合文字。例如
int (*p)[2] = (int[2][2]){{1,2},{3,4}};
或
int (*p)[2] = (int[][2]){{1,2},{3,4}};
这是一个演示程序。
#include <stdio.h>
int main(void)
{
enum { N = 2 };
int ( *p )[N] = ( int[N][N] ){ { 1, 2 }, { 3, 4 } };
for ( size_t i = 0; i < N; i++ )
{
for ( size_t j = 0; j < N; j++ )
{
printf( "%d ", p[i][j] );
}
putchar( '\n' );
}
putchar( '\n' );
int a[N][N] = { { 1, 2 }, { 3, 4 } };
p = a;
for ( size_t i = 0; i < N; i++ )
{
for ( size_t j = 0; j < N; j++ )
{
printf( "%d ", p[i][j] );
}
putchar( '\n' );
}
putchar( '\n' );
int b[N] = { 1, 2 };
p = &b;
for ( size_t i = 0; i < N; i++ )
{
printf( "%d ", ( *p )[i] );
}
putchar( '\n' );
return 0;
}
程序输出为
1 2
3 4
1 2
3 4
1 2
答案 1 :(得分:2)
{{1,2}};
是一个数组初始值设定项,而不是一个数组。所以代码是无效的 C - 你不能像那样初始化一个指针。这是错误的类型 int
和错误的初始化器数量。(int **){{1,2},{3,4}};
是类型为 int**
的复合文字。但同样,像这样初始化指针是无效的 C。(int[][]){{5,4},{5,6}};
是一个不完整类型的数组。无法初始化。所以这也是无效的 C。您的所有问题都源于忽略编译器警告。对于类似 gcc 的编译器,我强烈建议将您的设置更改为 -std=c11 -pedantic-errors
。那么当你编写无效的 C 时,你会得到编译器错误,而不仅仅是警告。
回答问题的正确方法是:
int (*p)[2] = (int[2][2]){ {1,2}, {3,4} };
这将创建一个与指针 p
具有相同作用域的局部作用域二维数组。这相当于:
int arr[2][2] = { {1,2}, {3,4} };
int (*p)[2] = arr;