c语言中二维数组的问题
2012-11-13 16:25
99 查看
在论坛上看到一个关于二维数组讨论的帖子,觉得很有价值就整理了一下转帖了过来
1)二维数组 参数传递 和二维数组的定义是一个道理。
二维数组声明时要求给定第二维下标。(同样,多维数组声明时要求给定除第一维外其他所有维的下标)
这是因为不管几维数组在内存中的存储和一维数组没有本质区别,都是线性存储的,长度是各个维下标之积。
程序运行时访问二维数组的某元素时要靠各维下标作偏移指标,比如a[10][3],只有给定第二维下标“3”,
当你写a[10]时,程序才知道要从a这个位置向后移动10个“3”。
参数的道理相同,也是局部变量的一种,和你在函数中声明的变量没有太大区别(栈中的位置不同)。
所以必须这样写:void trans(int a[][3], int b[]);
#include <stdio.h>
#include <stdlib.h>
void trans(int a[][3], int b[]);
int main(void)
{
int a[3][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
int b[9];
int i;
trans(a, b);
for (i = 0; i < 9; i++)
printf("%d/t", b[i]);
printf("/n");
exit(0);
}
void trans (int a[][3], int b[]) { //形参
int i, j, k;
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
b[k++] = a[i][j];
}
}
}
二维数组做参数
#include <iostream>
using namespace std;
void pb(char** a)
{
cout<<a[1][1];//只是测试调用成功不
}
int main()
{
char a[2][2];
for(int k=0;k<2;k++) {
for(int w=0;w<2;w++)
cin>>a[k][w];
}
pb((char **)a);
//二维数组做参数强制转换也有错!
return 0;
}
有什么好办法传递参数,吗,最好能有完整程序!谢谢
提问者: yjc_5252 - 试用期 一级 最佳答案
#include <iostream>
using namespace std;
void pb(char a[][2])
//一楼的稍改下,100改为2,即 a[][2]
{
cout<<a[1][1];
}
int main()
{
char a[2][2];
for(int k=0;k<2;k++){
for(int w=0;w<2;w++)
cin>>a[k][w];
}
pb(a);
return 0;
}
参考资料:一楼
0回答者: 江玉菡 - 试用期 一级 2009-5-25 20:56
其他回答 共 1 条
#include <iostream>
using namespace std;
void pb(char a[][100])
{
cout<<a[1][1];
}
int main()
{
char a[2][2];
for(int k=0;k<2;k++)
for(int w=0;w<2;w++)
cin>>a[k][w];
pb(a);
return 0;
}
搞人的二维数组指针,求助!
事情是这样的,我们老师说对于声明如下的
int a[4][5];
a这个二维数组,它的类型实际上是int**,
但是我在编程的时候试,写了下面的代码:
int a[4][5];
int** p = a;
VC中说不能将int [4][5]转化成int**,
BCB和Dev-C++中说
不能将int (*)[5]转化成int**,
所以我想应该是老师弄错了,
实际上一个二维数组的类型是int (*)
(其中n是第二维的维数),
用
int (*p)[5] = a;
就行了。
我跟我们老师说,她坚持说int**是对的。
大家怎么看啊?我都有点晕了。
2 楼goodboy1881
如果要如此写,你写
int** p =(int**)a;
尝试一下。
要不然你说这个a怎么解释,是二维数组第一行的首指针?还是二维数组的首指针?
3 楼
她说二维数组是int**型的,但是赋值指针的时候和类型又是不一样的,两者是有区别的。
所以我感到很奇怪,为什么赋值的时候不一样的,还要说二位数组是int**,
要不然为什么不能用一个int**的指针指向它呢?这不是明显的赋值不相容吗?
5 楼SaiRose(Learning......)
指针!=数组名
int a[4][5]它的类型绝对不是int**
只是函数在传参数的时候会将数组转化为指针
具体的查书了,c专家编程上有详细讲解
6 楼qingyuan18(zealot_tang)
二维数组名不能简单理解成二维的指针,
int a[4][5];
a是二维数组的首地址,但它不是一个int **型的指针。
int** p = a;
这样赋值是错误的,用指针对二维数组的操作应该参考用指针数组(int * p[4])
或者或者行指针((int *)p[4])的方式
7 楼anyy0929()
同意上面的,a是二维数组的首地址,
而P是指向指针的指针,不能这样赋值~~~
8 楼ywhs()
我想问的是int a[5][3]中a的类型是int**吗?
12 楼FreeFice(庄鱼)
int **用于表示二维数组的缺点在于指针的间隔无法确定,因此,虽然,int**可以描述二维数组,但地址并不是“自动”的一次性赋给的,作为定长多维数组,在很多时候可以被当作一位数组直接操作,然而,多级指针却绝不可以这样,这是数组与指针最本质的区别。如果一定要问int**与什么数组形式相对的话,int** = int[][],
而int[][]与int[5][3]完全是两回事。
13 楼
多维数组在意义上和指针完全不是一回事了
指针是一个间接指向的过程
但是多维数组,确实一个定点计算的问题
作为参数传递的时候,也不能如此直接传递
必须强制转化为一维数组,然后给出各个原始纬度的大小,再通过计算偏移得到原始数据
14 楼
给个例子
int a[2][3];
int** p;
p = new int*[2];
p[0] = new int[3];
p[1] = new int[3];
然后你反汇编这段代码:
a[1][2] = 5;
p[1][2] = 5;
汇编代码都不一样...
a[1][2] = 5;
00416AFE mov dword ptr [ebp-8], 5
p[1][2] = 5;
00416B05 mov eax, dword ptr [p]
00416B08 mov ecx, dword ptr [eax+4]
00416B0B mov dword ptr [ecx+8], 5
这个是我针对我的例子反汇编的结果,认为可以相互转换的朋友,可以看看
15 楼
这么用
int a[4][5];
int** p = &a[0];
其实区别就在二维数组的空间为连续,而二维指针申请的堆空间不是。
18 楼
二维数组名不能简单理解成二维的指针,int a[4][5];
a是二维数组的首地址,也是数组第一行的首地址(在数值上是一样的),但它不完全等同于一个int **型的指针。
int** p = a;这样赋值是可以的,多维数组就只能用多层的指针,(使用数组名除外)。至少这点在TC中是完全正确的,也许VC有不同的规定!!
19 楼
可以用,不代表会正确,下面这个代码在C中都没有问题:
char c;
int* p;
c = 'a'
p = &c;
*p = 65535;
赋值确实可以,但是执行结果不会正确...
20 楼
int[][]是什么意思?
为什么int** == int[][]?
int[][]与int[5][4]分别表达什么?有什么区别?
21 楼
其实,int a[4][5];
这种型式中,a的类型为:int (* )[5];
是的,编译器会把最后一维的数量做为类型的一种参考,更严格一点说的话,应该是:int (* const )[5];
22 楼
int a[4][5];
这种型式的的确确会在“很多时候可以被当作一位数组直接操作”。但最好不要这样做,我觉得不安全。
23 楼
int [][]二维不定数组,
C/C++中并不允许这样描述,根据C/C++对数组的定义要求:在做参数声明时,仅允许存在一个[](第一个)以表示数组大小的不确定性。数组大小在非参数声明时必须明确指明或初始化的。上面用int [][] <=> int **主要目的在于表述没有一种数组形式可以与int**相对应。指针*与数组[]实际上是不能用等号相联系的,唯一的例外是字符串char*与char[]一致,但实际上,字符串并不是什么指针,而是类似于隐式链表的数组(必须满足空字节结束表示),用于写成指针格式纯属早期编程习惯。千万不能拿来当验证指针与数组关系的工具。
由于指针的外延比数组(包括不定数组)大得多,因此,通常可以将A[4][5]赋值给B[][5]赋值给*C[5],但反过来却是不行的。
关于二维数组指针的问题
这是主函数
main()
{
int a[3][4]={{1,1,2,3},{4,5,6,7},{8,9,10,11}};
printf(" %u/n %u/n %u/n %u/n %u/n %u/n",
a+1,a[1],&a[1][0],*(a+1),*((a+1)+2),*(*(a+1)+2));
}
输出的结果是
65480
65480
65480
65480
65496
6
我想问一下从前三个可以看出a+1==*(a+1)可是为什么
*((a+1)+2)和*(*(a+1)+2)的结果不一样谁能能解释一下吗
其实这是C在实现多维数组时的魔术而已,实际上a就是一个12个int的数据区。你在写a[1][2]时编译器实际上知道这个数组一行是4个元素,所以计算它的地址为a+(1*4)+2,即a[1][2]就是*(a+(1*4)+2)。
另一方面,编译器允许使用形如a[1]这样的表述,由于它知道a是一个定义为a[3][4]的数组,所以它知道a+1实际上应该将a这个首地址加上4个int的大小,你如果再试一下就会发现在int为4个字节的机器上a[1]应该是a加上4.
C语言中的指针的值虽然可能是同一个内存地址,但是编译器知道它的语言不同,在做同样的指针增量的时候加的地址也是不同的。就像你如果把a的值强制转换成char *,比如char *p = (char *)a;再看p+1就只是指向a[0][0]的第二个字节了一样。同样的+1,含义却是不同的。
这样你就应该明白了,虽然*(a+1)的值只能是跟a+1一样,因为它也只能指向a[1][0],但是编译器知道它再增量的话就只需要加上1个int的大小,而不是4个int的大小了。因此*((a+1)+2)实际上是指向a[3],而*(*(a+1)+2)就是*(a[1]+2),也就是a[1][2]了。
#include<stdio.h>
void f(int a[][3])
{
a[1][1]=32;
a[1][2]=348;
}
int main()
{
int a[3][3];
f(a);
int *b;
b=(int *)a;
printf("%d",*(*(a+1)+2));
printf("%d",*(b+5));
scanf("%d");
return 0;
}
a+1代表第二行的首地址,(性质仍为二重数组)因此,a[1][2]可以用*(*(a+1)+2)来访问。
二重数组也可以用一维指针来访问,因为二维数组在内从中是按照从左到右从上到下的顺序排列的。b+5是第五个数的地址,按照二维数组在内存中排列的方法也就是a[1][1].
二维数组还可以用二维指针来访问:
#include<stdio.h>
void f(int a[][3])
{
a[1][1]=32;
a[1][2]=348;
}
int main()
{
int a[3][3];
f(a);
int (*p)[3];
p=a;
printf("%d",p[1][1]);
scanf("%d");
return 0;
}
上面的p表示指向二维数组的指针,该数组每行共计四个元素。
注意与char *a[4]相区别。后者是一个指针数组,每一个数组元素指向char型元素。
1)二维数组 参数传递 和二维数组的定义是一个道理。
二维数组声明时要求给定第二维下标。(同样,多维数组声明时要求给定除第一维外其他所有维的下标)
这是因为不管几维数组在内存中的存储和一维数组没有本质区别,都是线性存储的,长度是各个维下标之积。
程序运行时访问二维数组的某元素时要靠各维下标作偏移指标,比如a[10][3],只有给定第二维下标“3”,
当你写a[10]时,程序才知道要从a这个位置向后移动10个“3”。
参数的道理相同,也是局部变量的一种,和你在函数中声明的变量没有太大区别(栈中的位置不同)。
所以必须这样写:void trans(int a[][3], int b[]);
#include <stdio.h>
#include <stdlib.h>
void trans(int a[][3], int b[]);
int main(void)
{
int a[3][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
int b[9];
int i;
trans(a, b);
for (i = 0; i < 9; i++)
printf("%d/t", b[i]);
printf("/n");
exit(0);
}
void trans (int a[][3], int b[]) { //形参
int i, j, k;
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
b[k++] = a[i][j];
}
}
}
二维数组做参数
#include <iostream>
using namespace std;
void pb(char** a)
{
cout<<a[1][1];//只是测试调用成功不
}
int main()
{
char a[2][2];
for(int k=0;k<2;k++) {
for(int w=0;w<2;w++)
cin>>a[k][w];
}
pb((char **)a);
//二维数组做参数强制转换也有错!
return 0;
}
有什么好办法传递参数,吗,最好能有完整程序!谢谢
提问者: yjc_5252 - 试用期 一级 最佳答案
#include <iostream>
using namespace std;
void pb(char a[][2])
//一楼的稍改下,100改为2,即 a[][2]
{
cout<<a[1][1];
}
int main()
{
char a[2][2];
for(int k=0;k<2;k++){
for(int w=0;w<2;w++)
cin>>a[k][w];
}
pb(a);
return 0;
}
参考资料:一楼
0回答者: 江玉菡 - 试用期 一级 2009-5-25 20:56
其他回答 共 1 条
#include <iostream>
using namespace std;
void pb(char a[][100])
{
cout<<a[1][1];
}
int main()
{
char a[2][2];
for(int k=0;k<2;k++)
for(int w=0;w<2;w++)
cin>>a[k][w];
pb(a);
return 0;
}
搞人的二维数组指针,求助!
事情是这样的,我们老师说对于声明如下的
int a[4][5];
a这个二维数组,它的类型实际上是int**,
但是我在编程的时候试,写了下面的代码:
int a[4][5];
int** p = a;
VC中说不能将int [4][5]转化成int**,
BCB和Dev-C++中说
不能将int (*)[5]转化成int**,
所以我想应该是老师弄错了,
实际上一个二维数组的类型是int (*)
(其中n是第二维的维数),
用
int (*p)[5] = a;
就行了。
我跟我们老师说,她坚持说int**是对的。
大家怎么看啊?我都有点晕了。
2 楼goodboy1881
如果要如此写,你写
int** p =(int**)a;
尝试一下。
要不然你说这个a怎么解释,是二维数组第一行的首指针?还是二维数组的首指针?
3 楼
她说二维数组是int**型的,但是赋值指针的时候和类型又是不一样的,两者是有区别的。
所以我感到很奇怪,为什么赋值的时候不一样的,还要说二位数组是int**,
要不然为什么不能用一个int**的指针指向它呢?这不是明显的赋值不相容吗?
5 楼SaiRose(Learning......)
指针!=数组名
int a[4][5]它的类型绝对不是int**
只是函数在传参数的时候会将数组转化为指针
具体的查书了,c专家编程上有详细讲解
6 楼qingyuan18(zealot_tang)
二维数组名不能简单理解成二维的指针,
int a[4][5];
a是二维数组的首地址,但它不是一个int **型的指针。
int** p = a;
这样赋值是错误的,用指针对二维数组的操作应该参考用指针数组(int * p[4])
或者或者行指针((int *)p[4])的方式
7 楼anyy0929()
同意上面的,a是二维数组的首地址,
而P是指向指针的指针,不能这样赋值~~~
8 楼ywhs()
我想问的是int a[5][3]中a的类型是int**吗?
12 楼FreeFice(庄鱼)
int **用于表示二维数组的缺点在于指针的间隔无法确定,因此,虽然,int**可以描述二维数组,但地址并不是“自动”的一次性赋给的,作为定长多维数组,在很多时候可以被当作一位数组直接操作,然而,多级指针却绝不可以这样,这是数组与指针最本质的区别。如果一定要问int**与什么数组形式相对的话,int** = int[][],
而int[][]与int[5][3]完全是两回事。
13 楼
多维数组在意义上和指针完全不是一回事了
指针是一个间接指向的过程
但是多维数组,确实一个定点计算的问题
作为参数传递的时候,也不能如此直接传递
必须强制转化为一维数组,然后给出各个原始纬度的大小,再通过计算偏移得到原始数据
14 楼
给个例子
int a[2][3];
int** p;
p = new int*[2];
p[0] = new int[3];
p[1] = new int[3];
然后你反汇编这段代码:
a[1][2] = 5;
p[1][2] = 5;
汇编代码都不一样...
a[1][2] = 5;
00416AFE mov dword ptr [ebp-8], 5
p[1][2] = 5;
00416B05 mov eax, dword ptr [p]
00416B08 mov ecx, dword ptr [eax+4]
00416B0B mov dword ptr [ecx+8], 5
这个是我针对我的例子反汇编的结果,认为可以相互转换的朋友,可以看看
15 楼
这么用
int a[4][5];
int** p = &a[0];
其实区别就在二维数组的空间为连续,而二维指针申请的堆空间不是。
18 楼
二维数组名不能简单理解成二维的指针,int a[4][5];
a是二维数组的首地址,也是数组第一行的首地址(在数值上是一样的),但它不完全等同于一个int **型的指针。
int** p = a;这样赋值是可以的,多维数组就只能用多层的指针,(使用数组名除外)。至少这点在TC中是完全正确的,也许VC有不同的规定!!
19 楼
可以用,不代表会正确,下面这个代码在C中都没有问题:
char c;
int* p;
c = 'a'
p = &c;
*p = 65535;
赋值确实可以,但是执行结果不会正确...
20 楼
int[][]是什么意思?
为什么int** == int[][]?
int[][]与int[5][4]分别表达什么?有什么区别?
21 楼
其实,int a[4][5];
这种型式中,a的类型为:int (* )[5];
是的,编译器会把最后一维的数量做为类型的一种参考,更严格一点说的话,应该是:int (* const )[5];
22 楼
int a[4][5];
这种型式的的确确会在“很多时候可以被当作一位数组直接操作”。但最好不要这样做,我觉得不安全。
23 楼
int [][]二维不定数组,
C/C++中并不允许这样描述,根据C/C++对数组的定义要求:在做参数声明时,仅允许存在一个[](第一个)以表示数组大小的不确定性。数组大小在非参数声明时必须明确指明或初始化的。上面用int [][] <=> int **主要目的在于表述没有一种数组形式可以与int**相对应。指针*与数组[]实际上是不能用等号相联系的,唯一的例外是字符串char*与char[]一致,但实际上,字符串并不是什么指针,而是类似于隐式链表的数组(必须满足空字节结束表示),用于写成指针格式纯属早期编程习惯。千万不能拿来当验证指针与数组关系的工具。
由于指针的外延比数组(包括不定数组)大得多,因此,通常可以将A[4][5]赋值给B[][5]赋值给*C[5],但反过来却是不行的。
关于二维数组指针的问题
这是主函数
main()
{
int a[3][4]={{1,1,2,3},{4,5,6,7},{8,9,10,11}};
printf(" %u/n %u/n %u/n %u/n %u/n %u/n",
a+1,a[1],&a[1][0],*(a+1),*((a+1)+2),*(*(a+1)+2));
}
输出的结果是
65480
65480
65480
65480
65496
6
我想问一下从前三个可以看出a+1==*(a+1)可是为什么
*((a+1)+2)和*(*(a+1)+2)的结果不一样谁能能解释一下吗
其实这是C在实现多维数组时的魔术而已,实际上a就是一个12个int的数据区。你在写a[1][2]时编译器实际上知道这个数组一行是4个元素,所以计算它的地址为a+(1*4)+2,即a[1][2]就是*(a+(1*4)+2)。
另一方面,编译器允许使用形如a[1]这样的表述,由于它知道a是一个定义为a[3][4]的数组,所以它知道a+1实际上应该将a这个首地址加上4个int的大小,你如果再试一下就会发现在int为4个字节的机器上a[1]应该是a加上4.
C语言中的指针的值虽然可能是同一个内存地址,但是编译器知道它的语言不同,在做同样的指针增量的时候加的地址也是不同的。就像你如果把a的值强制转换成char *,比如char *p = (char *)a;再看p+1就只是指向a[0][0]的第二个字节了一样。同样的+1,含义却是不同的。
这样你就应该明白了,虽然*(a+1)的值只能是跟a+1一样,因为它也只能指向a[1][0],但是编译器知道它再增量的话就只需要加上1个int的大小,而不是4个int的大小了。因此*((a+1)+2)实际上是指向a[3],而*(*(a+1)+2)就是*(a[1]+2),也就是a[1][2]了。
#include<stdio.h>
void f(int a[][3])
{
a[1][1]=32;
a[1][2]=348;
}
int main()
{
int a[3][3];
f(a);
int *b;
b=(int *)a;
printf("%d",*(*(a+1)+2));
printf("%d",*(b+5));
scanf("%d");
return 0;
}
a+1代表第二行的首地址,(性质仍为二重数组)因此,a[1][2]可以用*(*(a+1)+2)来访问。
二重数组也可以用一维指针来访问,因为二维数组在内从中是按照从左到右从上到下的顺序排列的。b+5是第五个数的地址,按照二维数组在内存中排列的方法也就是a[1][1].
二维数组还可以用二维指针来访问:
#include<stdio.h>
void f(int a[][3])
{
a[1][1]=32;
a[1][2]=348;
}
int main()
{
int a[3][3];
f(a);
int (*p)[3];
p=a;
printf("%d",p[1][1]);
scanf("%d");
return 0;
}
上面的p表示指向二维数组的指针,该数组每行共计四个元素。
注意与char *a[4]相区别。后者是一个指针数组,每一个数组元素指向char型元素。
相关文章推荐
- c语言--二维数组的首地址问题
- 一个关于C语言二维数组问题
- C语言中的二维数组问题
- C语言中关于指针,二维数组等的问题,一个有趣的发现
- C语言二维数组中的指针问题
- C语言二维数组作为形参传值问题
- C语言中的二级指针和二维数组问题
- C语言中二维数组的问题
- C语言二维数组中的指针问题
- 在c语言学习中的问题(一):数组指针,指针数组,二维数组的理解与区分
- C语言中的二级指针和二维数组问题
- C语言二维数组中的指针问题
- C语言中的二级指针和二维数组问题
- C语言为二维数组动态分配内存的问题
- C语言二维数组的指针及首地址问题
- 关于一个C语言二维数组的问题
- C语言中有关二维数组的指针问题
- C语言中的二级指针和二维数组问题
- 举例理解C语言二维数组的指针指向问题
- C语言结构体问题