定义(*p)[4]和p[][4](会产生错误)的区别
2010-03-29 11:45
225 查看
对C语言中一个数组指针及指针数组问题的分析
2009年02月07日 星期六 下午 11:49
2009年02月07日 星期六 下午 11:49
在百度知道里偶然看到一个问题,提问者的提问内容如下: #include "stdio.h" #define M 3 #define N 4 main() { int a[M] ,*p[M],j,k; for(j=0;j<M;j++) p[j]=a[j]; for(j=0;j<M;j++) for(k=0;k<N;k++) scanf("%d",&p[j][k]); for(j=0;j<M;j++) { for(k=0;k<N;k++) printf("%5d",p[j][k]); } } 上面程序没有问题,但是在定义方面,教材上说a[j]是常量,而p[j]为变量,我认为这两者皆为指针变量(一级),(就因为上面的第一个for语句).不知我错了,还是教材错了,请各位指教 ======================================================================================================================== 还有,在定义"行指针"的时候,例如: int a[3][4],(*p)[4]; 我认为(*p)[4]等价于p[][4]; 可在以"后者"调用的时候出现语法错误; ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× 对此问题做一个简要分析,如下: 首先明确一点,即如果定义了 int (*p)[4];就压根没有p[][4]这一说,定义了以后p代表内存空间仅仅可以存放一个指针值,并且这个指针值只能是一个长度为4的整形数组的首地址,所以p[][4]这个形式是错误的,同理int *p[4]则是一个指针数组,可以存放四个整形变量的地址. 在c语言中,数组名,以及**数组的数组名+第一个维数,分别表示数组首地址和第几行元素所占空间的首地址,和指针并不是同一种类型数据,指针可以指向任何一个存放定义数据类型的空间地址,即其值是可变的,而以数组名命名的变量代表系统预先编址空间的地址,对它赋值意味着强制为变量代表的空间强制重新编址,系统是不允许地,只允许以下标访问元素方式对空间中存储的数据变量进行赋值操作. 在这段程序里,*(a+j)和a[j]是等效的,都代表第j行元素所占空间首地址.而int *p[M]和int (*p)[4]是不一样的,前者是一个指针数组,这个数组可放M个指针元素,后一个是数组指针,它只能指向一个有四个元素的数组,但是并没有p[][4]这种说法,因为(*p)[4]只是一个单独的变量,它指向的空间只能存储一个值,就是一个有长度为4的一维数组首地址或一个二维数组某一行数中据所占空间首地址. 就是说,假如这样定义,int a[3][4],(*p)[4],那么可以这样使用 for ( int i = 0; i < 3; ) { //p是一个数组指针变量而不是数组变量,不能用p[]或p[][]这种形式 p = a[i++]; for ( int j = 0; j < 4; ) printf( *(*(p+0)+j++) );//scanf("d%",&*(*(p+0)+j++)); } 或者 //p是一个数组指针变量而不是数组变量,不能用p[]或p[][]这种形式 p = a; for ( int i = 0; i < 3; ) { for ( int j = 0; j < 4; ) printf( *(*(p+i++)+j++) );//scanf("d%",*(*(p+i++)+j++) ); } 同理, int a[M] ,*p[M],j,k; for(j=0;j<M;j++) p[j]=a[j];//或者p[j]=&a[j][N个中的某一个值] 这种情况下,数组p(不是指针p)里面放了M个地址,它们是数组a的M行数据所占空间的首地址或者每行数组第一个元素的地址.用这个值的时候就应该这样用 for(j=0;j<M;j++) { for(k=0;k<N;k++) { //p是一组数组变量,只能以p[x]或*(p+x)这两种形式使用 scanf("%d",&*(p[j]+k)); //scanf("%d",&*(*(p+j)+k)); } } for(j=0;j<M;j++) { for(k=0;k<N;k++) { //同理,输出时也只能以p[x]或*(p+x)这两种形式使用 printf("%5d",*(p[j]+k)); printf("%5d",*(*(p+j)+k)); } } |
相关文章推荐
- C语言学习7 :二级指针定义,强制转换,多级指针初步,6级指针构造,错误应用*p=&a,错误应用 二级p2,void型指针的兼容性,malloc函数基本用法,malloc分配空间和堆栈空间的区别,验证malloc函数内存的分配,验证malloc函数的越界,内存泄漏,指针不能返回局部变量地址,内存分配
- 软件缺陷与软件错误的定义与区别
- 定义const对象而产生的常数据成员与直接定义const数据成员在编译器编译时候的区别
- C++ 类的成员函数定义在.h中为什么会产生函数重定义错误?
- c++中静态成员变量要在类外部再定义,否则产生link2001错误.
- 在Spring里定义多个同名bean产生的错误
- Qt事件机制浅析(定义,产生,异步事件循环,转发,与信号的区别。感觉QT事件与Delphi的事件一致,而信号则与Windows消息一致)
- 汇编学习之路(二)标号后定义数据产生错误
- Eclipse中启动Tomcat服务器产生错误的原因及解决方案
- javascript定义变量时带var与不带var的区别分析
- IE8下提示'console'未定义错误
- js中let和var定义变量的区别
- window.setInterval()方法的定义和用法及offsetLeft与style.left的区别
- 变量声明和定义的区别
- [转载]定义、公理、定理、推论、命题和引理的区别
- 用户控件和自定义控件的定义及区别
- Java、C#、C++定义数组区别
- 小黑小波比.在app端定义并提示错误信息
- PHP基础教程(九)字符串定义及单双引号的区别
- 引用三方Dll时,产生“does not have a strong name”错误