指针数组 与数组指针

来源:互联网 发布:淘宝店铺信用怎么看 编辑:程序博客网 时间:2024/04/30 10:17

#define MAX 10 

char* ch1[MAX];// max个字符串 (指针数组)

(char*)  ch2[MAX];//错误 在vc6上编译不过

char (* ch3)[MAX];//含有MAX个字符的指针;即数组指针

  ch3=(char (*)[12])malloc(12); 

or

 ch3 = &ch1; 

 

 

ch1={"hello","world",};

ch3 ={"nihaoa"}; //错误 在vc6上编译不过


部分摘自:http://ankorzhang.blog.163.com/blog/static/11837734320097261073438/ 

int *p[2]; 首先声明了一个数组,数组的元素是int型的指针。
int (*p)[2]; 声明了一个指针, 指向了一个有两个int元素的数组。

 通常,对于int a[8][9]这个二维数组,我们可以这样定义一个指向它的指针:


int (*p)[9];

 

这个声明的形式跟人们所熟悉的int *p的形式大相庭径,初学者通常会感到迷惑,不理解的地方大致有四个:

1。为什么会以这种形式声明?

2。(*p)应该如何理解?

3。为什么必须把第二维显式地声明?

4。为什么忽略第一维?

下面我们就一起逐个讨论这四个问题:

1。这种形式是C标准的声明语法规定的,由于本章不是对标准的解释,只是对标准的应用,因此笔者尽量以简洁的方式解释这个声明,详细的讨论将在第七章进行。C标准的声明包含了两部分:

声明:

声明说明符  初始化声明符表opt      (opt的意思是可选)

在声明说明符里面有一项类型说明符,int就是这种类型说明符。而初始化声明符表里面的其中一种形式,就是:

直接声明符 [常量表达式opt]

(*p)[9]就是这种直接声明符加[]的形式。

2。p左边的*在这里不是取值运算符,而是一个声明符,它指出p是一个指针。而()括号是不能去掉的,如果去掉了,由于[]运算符优先级比*高,p就会先跟[]结合,这样p就变成了一个指针数组,而不是指向数组的指针。

题外话:

*p还有一种用法,就是当*是取值运算符的时候,*p是一个左值,表示一个变量,为什么*p是一个变量呢?也许有人会说,因为int i, *p=&i嘛,其实这是结果不是原因。严格来说,i只是一个变量名,不是变量,在编译器的符号表里面,变量名是一个符号地址,它所代表的地址值是它指向的那段内存单元的地址,真正叫变量的是那段内存单元,懂汇编的朋友能很容易地区分出来,在汇编里面,可以这样定义一个变量名:

VARW  DW  10,20

VARW就是一个变量名,它在汇编里面是一个地址,代表了10所在的内存单元这个变量。由于p被初始化为&i,*p指向i所代表的那段内存单元,因此说*p是一个变量。把i称为变量是一种习惯上的统称。

3。定义一个指针的时候,首先必须定出指针的类型,由于这是一个指向数组的指针,如果数组的元素的类型定下来了,那么这个指针的类型也就定下来了。前面说过,C语言的多维数组实质上是数组的嵌套,那么所指向数组的元素必定具有数组类型,也就是说,这个数组的元素是一个具有6个int元素的数组,因此,p定义的时候,必须指定第二维的上界,这样才能把p的类型定下来。

4。有这种疑问的人已经犯了一个错误,没有分清楚什么是指针,什么是数组,以数组的思维模式来看待这个指针p。定义一个数组(非static)的时候,需要在栈中静态分配一块内存,那么就需要知道这块内存的大小,因此定义数组时需要确定各维的上界。而这里只是定义一个指针而已,对于一个指针的定义,需要知道的是它所指向对象的类型,并不需要知道对象的大小,这是多余的。因此,所有指向数组的指针的第一维被忽略。

        以上介绍了如何声明一个指向二维数组的指针,类似地,对一个指向n维数组的指针也可以用同样的方法来声明,如下:

int (*p)[x2][x3]......[xn];

同样可以忽略第一维,而其它维必须指定上界。

        最后再讨论一种很常见的对多维数组的错误理解,有些人常常会以为,二维数组就是二级指针,这种错误的根源,来自于可以把一个二级指针int **p以p[i][j]这种形式使用。首先把数组称为指针就是错误的,第一章笔者已经说明了数组名是地址,不能理解为指针。第二,并非能以p[i][j]这种形式使用,那么p就是一个二维数组了,C标准对数组引用的规定,并没有指定数组引用时[]运算符的左边必须是数组名,而可以是一个表达式。第三,这是一种“巧合”,归根到底是由于C语言的数组实现是数组的嵌套同时C标准把[]运算符转换为类似*(*(a+i)+j)这样的等价表达式造成的,那两个取值运算符“恰好”可以用于一个二级指针。第四,p与p[i]并不具有数组类型,sizeof(p)和sizeof(p[i])的结果只是一个指针的大小4字节。而对于一个真正的数组,p与p[i]都是具有数组类型的地址。

        实际上,int **p只是一个指向一维指针数组的指针,而不是指向二维数组的指针。同样地,对于n级指针,都可以看作一个指向一维指针数组的指针,这个指针数组的元素都是n-1级指针。




【huashizhixin】:
一个指向十个int元素的指针
可以这样赋值:int b[10]={0};//必须是十个元素
   p=&b;

【huashizhixin】:
(i)int *p[3]; 
(ii)int (*q)[3]; 
(iii)int *(t[3]); 
以上三者的区别?(vc++环境下验证): 
(1)p是一个指针数组,此处包含三个整型指针,所以sizeof(p)=12;sizeof(*p)=4;//首地址 
    
(2)q是一个数组指针,指向含有三个元素的整型数组,所以sizeof(q)=4;sizeof(*q)=12; 

(3) 和(1)一样;sizeof(t)=12;sizeof(*t)=4; 

(4)   int *p[3]等价于:typedef        int*    myint; 
                                  myint  p[3]; 
                   int (*p)[3]等价于:typedef     int    intarray[3]; 
                                  intarray  *p; 
(5)   (i)可以这样初试化:int  a[]={1,2,3,4}; 
                 p[0]=a;//*p=a;  
      (ii)可以这样初始化:int  a[3]={1,2,3};//数组元素必须是三个 
                  q =&a; 
(6)p是数组,不可做++操作,q是指针,可以做++操作,q++是当前q指向的地址值加12;

【hongliuhongwei】:
谢谢大家,能不能给我一个使用的例子啊,我是在使用的时候,编译能通过,一执行就有问题,没有结果,谢谢!

【huashizhixin】:
vc6.0
#include"stdio.h"
main(int argc,  char *argv[ ])
{
int b[3]={1,2,3};
int (*p)[3];
p=&b;
for(int i=0;i<3;i++)
printf("%5d",*(*p+i));
}

【cuibo1123】:
int (*p)[10]
整形 指针 10个元素
 意思就是一个指针,可以指向包含10个整形元素的东西~

int main(void)
{
   int a[5][10]={1};//5行10列的数组(也就是5个  《包含10个整形元素》 的数组)
   int (*p)[10];//可以指向包含10个整形元素的指针(他的基类型是sizeof(int)*10)
   p=a;
   printf("%d",p[0][0]);
   return 0;
}
原创粉丝点击