您的位置:首页 > 其它

C中二级指针与它指向的一级指针之间的秘密(深入++*pptr)

2018-01-08 22:52 471 查看
C语言里二级指针的意思是指向指针的指针,一级指针就是普通的指针,一个二级指针一定是对应着一个一级指针,那么二级指针和这个它对应的一级指针之间有什么秘密呢?

1. 首先明白在二级指针使用中 ++*pptr 与 *pptr++ 之间的区别

首先申明一下,这里的pptr和标题中的一样,都代表着指向指针的指针,是一个二级指针,所以用了两个'p'来表示嘛。接下来看下面的代码:

int main(int argc, char ** argv)
{
char * ar[5] = {"ruby", "java", "c++", "python", "js"};//定义一个含5个指针元素的指针数组
char ** pptr = ar;//定义一个二级指针,并初始化为ar

printf("pptr = %p\n", pptr);
printf("*pptr = %p\n", *pptr);
printf("++*pptr = %p\n", ++*pptr);
}

程序的输出是:



第一行输出都明白,第二行第三行地址却仅仅加了1,说明第三行是"ruby"中u的地址。

那么换成*pptr++呢?

程序的输出是:



我们发现,地址并没有加1,那是因为在*pptr++中,pptr先和++结合,但是它所代表的是自增之前的地址,再用*运算符获取到一个它对应的一级指针,所以打印出来的地址并没有改变。而在++*pptr中,pptr先和*运算符结合,得到它所对应的一级指针,再对这个一级指针++,且是自增之后的地址,所得到的地址自然是加了1。

注意:*pptr++虽然地址没有变,但是它仍然是递增的,增了多少?实际上增的是二级指针,所以结果是404005。



2. 重点:深入++*pptr

先看下面一段代码:

int main(int argc, char ** argv)
{
char * ar[5] = {"ruby", "java", "c++", "python", "js"};//定义一个含5个指针元素的指针数组
char ** pptr = ar;//定义一个二级指针,并初始化为ar
char ** pptr_t = ar;//复制一份pptr

printf("*++*pptr = %c\n", *++*pptr);
printf("**pptr_t = %c\n", **pptr_t);
}

输出是多少呢?
有人的答案是:*++*pptr = u, **pptr_t = r

很遗憾,答案是错的,不过答对了一半,*++*pptr = u 是正确的,那么**pptr_t又是多少呢?

肯定会有人疑问,pptr_t不是和pptr开始都一样吗,都是指针数组ar首元素的地址,pptr_t又没有进行别的操作,**pptr_t的值不应该仍然是r吗?

然而正确答案是:*++*pptr = u, **pptr_t = u !

原因在于:++*pptr操作已经将pptr对应的那个一级指针*pptr自增了,直接改变了指针数组中第一个指针元素,它指向的不再是r而是u,当下一次访问这个一级指针上的值时,即**pptr_t的值就是改变后的u了!

3. 应用:在处理命令行参数时遇到的问题

有些操作系统,包括UNIX和MS-DOS,让用户在命令行中编写参数来启动一个程序的执行。当在处理命令行参数时,有些程序允许用户在一个参数中放入多个选项字母,例如下面的一个命令行:

prog -abc name1 name2 name3


-abc是将-a,-b,-c三种选项字母结合在一起,同样拥有三种选项。这交由下面的一段代码来处理:

while (( opt = *++*argv) != '\0')
{
switch (opt)
{
case 'a':
option_a = TRUE;
break;
/*etc. */
}
}


可以看到,程序中运用了++*argv,所以我们要注意的是,使用这种方式,命令行参数可能只能处理一次,因为指向参数的指针在内层循环中被破坏,如果多次处理参数,当你挨个访问列表时,对每个需要增值的指针都做一份拷贝。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  二级指针