指针数组和数组指针

http://learn.akae.cn/media/ch23s06.html 
 
 

     
    呵呵,实在是厌倦了绕口的解释。

    指针数组,故名思义,就是指针的数组,数组的元素是指针;
    数组指针,同样,就是直想数组的指针。

    简单举例说明:

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

    其实这两种写法主要是因为运算符的优先级, 因为[]的优先级比*高。所以第一种写法,p先和[]结合,所以是一个数组,后与*结合,是指针。后一种写法同理。
    指针数组如下处理就会很清楚:
    typedef int* intPtr;
    intPtr p[2];
    一目了然,所以为了避免迷惑,做适当的typedef也是很有必要的。
    同理,数组指针也可以作类似处理:
    typedef int intArray2[2];
    intArray2 * p;
    和原来的声明都是等价的。
   
    个人建议编程过程中采用typedef来进行类型定义,这样程序看起来会清晰很多。举个例子说明:

    数组指针,元素为指向数组的指针:)
    首先,指向数组的指针为:
    typedef intArray2* intArray2Ptr;
    然后是一个数组的元素:
    typede intArray2Ptr intArray2PtrArr3[3];
    最后数组的指针:

    intArray2PtrArr3 *p;


    呵呵,写到这里自己也有点晕了,反正我工作以来从来没有写过这么拗口的程序,仅作参考,实际应用价值不大。
    但是开题所提到两种情况应该是比较常见的。另外就是函数指针。另外详述。

指向指针的指针与指针数组 请点评

指针可以指向基本类型,也可以指向复合类型,因此也可以指向另外一个指针变量,称为指向指针的指针。

int i;
int *pi = &i;
int **ppi = π

这样定义之后,表达式*ppipi的值,表达式**ppii的值。请读者自己画图理解ipippi这三个变量之间的关系。

很自然地,也可以定义指向“指向指针的指针”的指针,但是很少用到:

int ***p;

数组中的每个元素可以是基本类型,也可以复合类型,因此也可以是指针类型。例如定义一个数组a由10个元素组成,每个元素都是int *指针:

int *a[10];

这称为指针数组。int *a[10];int **pa;之间的关系类似于int a[10];int *pa;之间的关系:a是由一种元素组成的数组,pa则是指向这种元素的指针。所以,如果pa指向a的首元素:

int *a[10];
int **pa = &a[0];

pa[0]a[0]取的是同一个元素,唯一比原来复杂的地方在于这个元素是一个int *指针,而不是基本类型。

我们知道main函数的标准原型应该是int main(int argc, char *argv[]);argc是命令行参数的个数。而argv是一个指向指针的指针,为什么不是指针数组呢?因为前面讲过,函数原型中的[]表示指针而不表示数组,等价于char **argv。那为什么要写成char *argv[]而不写成char **argv呢?这样写给读代码的人提供了有用信息,argv不是指向单个指针,而是指向一个指针数组的首元素。数组中每个元素都是char *指针,指向一个命令行参数字符串。

例 23.2. 打印命令行参数

#include <stdio.h>

int main(int argc, char *argv[])
{
	int i;
	for(i = 0; i < argc; i++)
		printf("argv[%d]=%s\n", i, argv[i]);
	return 0;
}


 

编译执行:

$ gcc main.c
$ ./a.out a b c
argv[0]=./a.out
argv[1]=a
argv[2]=b
argv[3]=c
$ ln -s a.out printargv
$ ./printargv d e 
argv[0]=./printargv
argv[1]=d
argv[2]=e
 
由于 argv[4]NULL,我们也可以这样循环遍历 argv
for(i=0; argv[i] != NULL; i++)

NULL标识着argv的结尾,这个循环碰到NULL就结束,因而不会访问越界,这种用法很形象地称为SentinelNULL就像一个哨兵守卫着数组的边界。

在这个例子中我们还看到,如果给程序建立符号链接,然后通过符号链接运行这个程序,就可以得到不同的argv[0]。通常,程序会根据不同的命令行参数做不同的事情,例如ls -lls -R打印不同的文件列表,而有些程序会根据不同的argv[0]做不同的事情,例如专门针对嵌入式系统的开源项目Busybox,将各种Linux命令裁剪后集于一身,编译成一个可执行文件busybox,安装时将busybox程序拷到嵌入式系统的/bin目录下,同时在/bin/sbin/usr/bin/usr/sbin等目录下创建很多指向/bin/busybox的符号链接,命名为cplsmvifconfig等等,不管执行哪个命令其实最终都是在执行/bin/busybox,它会根据argv[0]来区分不同的命令。


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值