我知道二维数组作为一维数组存储在内存中。 因此,遵循相同的逻辑,我试图通过引用使用单个指针传递数组,就像对一维数组所做的那样。 以下是我的代码:
#include<stdio.h>
void display(int *s)
{
int i,j;
for(i=0;i<3;i++)
{
for(j=0;j<4;j++)
{
printf("%d ",s[i][j]);
}
printf("\n");
}
}
int main()
{
int s[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
printf("address of the array is %p\n",s);
printf("value is %p\n",*s);
int i;
printf("address of the repective array is\n");
for(i=0;i<3;i++)
{
printf("address of the array is %p\n",s[i]);
}
display(s);
return 0;
}
当我尝试编译此获取以下消息时:
twodarray.c: In function ‘main’:
twodarray.c:25:2: warning: passing argument 1 of ‘display’ from incompatible pointer type [enabled by default]
display(s);
^
twodarray.c:2:6: note: expected ‘int **’ but argument is of type ‘int (*)[4]’
void display(int *s[3])
^
当我运行上面的代码时,我得到了分段错误错误。
答案 0 :(得分:6)
函数参数声明为类型int *
void display(int *s)
虽然原始数组作为参数传递给函数,但是类型为
int [3][4]
隐式转换为指向其第一个具有类型
的元素的指针int ( * )[4]
正如您所看到的,int *
和int ( * )[4]
是两种不同的类型,并且没有从一种类型到另一种类型的隐式转换。
此外,由于函数参数的类型为int *
,因此您可能无法在函数表达式s[i][j]
中编写。因为如果要将下标运算符应用于此指针,例如s[i]
,则此表达式是int
类型的标量对象。它不是指针。所以你可能不会第二次应用下标运算符。
您必须将参数显式转换为函数调用中参数的类型。例如
display( ( int * )s );
您想要的是以下
#include <stdio.h>
void display( int *a, size_t m, size_t n )
{
for ( size_t i = 0; i < m; i++ )
{
for ( size_t j = 0; j < n; j++ )
{
printf( "%2d ", a[i * n + j] );
}
printf( "\n" );
}
}
int main( void )
{
int a[3][4] = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } };
printf( "The address of the array is %p\n", ( void * )a );
printf( "The address of the first row is %p\n", ( void * )*a );
printf("The address of the respective array rows are\n");
for ( size_t i = 0; i < 3; i++ )
{
printf( "address of row %zu is %p\n", i, ( void * )a[i] );
}
display( ( int * )a, 3, 4 );
return 0;
}
程序输出可能看起来如下
The address of the array is 0xbf85d2dc
The address of the first row is 0xbf85d2dc
The address of the respective array rows are
address of row 0 is 0xbf85d2dc
address of row 1 is 0xbf85d2ec
address of row 2 is 0xbf85d2fc
1 2 3 4
5 6 7 8
9 10 11 12
虽然以下列方式声明函数会更好,以避免不必要的转换和复杂的函数实现
void display( int ( *a )[4], size_t m );
答案 1 :(得分:2)
int[3][4]
类型的数组无法转换为int**
或int *[]
或int*
类型的指针。
问题是,
int s[3][4];
实际上将存储在物理连续内存中。要访问3x4数组的任意部分,函数display
需要知道数组的维数。
所以你应该将你的功能改为:
void display(int (*s)[4])
或使用更灵活的技术(Passing multidimensional arrays as function arguments in C)。
答案 2 :(得分:2)
像这里定义的静态二维数组在内存中以顺序一维数组的形式排列。但它不能像你试过的那样使用。通常编译器甚至不会生成此代码的二进制文件。
您可以通过巧妙地将指针转换为display()
来调用int*
函数。这不会有太大帮助,因为在函数内部它被编入二维索引,编译器不知道维度是什么。
这样想:如果你分配100个整数的线性内存块,是不是意味着它是一个大小为10x10,2x50或4x25的数组?无法知道,因此您无法将其索引为二维数组。此外,甚至可能不知道内存块有多大。
但是,您可以将其索引为一维数组,并将索引手动乘以s[i*4+j]
。这是有效的,因为如上所述,静态数组以线性方式存储在内存中,您可以手动告诉它如何读取它。
只是想知道你是如何设法实际编译代码的。
答案 3 :(得分:-1)
2维数组以行方式存储在内存中。因此,首先存储数组元素s [0] [0],然后存储s [0] [1],s [0] [2],s [0] [3],s [1] [0]。同样。
您已将指向被调用函数中的单维数组的指针作为参数。你所能做的就是改变printf(&#34;%d&#34;,s [i] [j]);声明 printf(&#34;%d&#34;,*(s + i + j));,这将有效。
最后的printf语句应编辑为printf(&#34;%d&#34;,*(s + 4 * i + j));正如以下评论所示。