例题一
#include<stdio.h>
int main()
{
int a[2][5]={1,2,3,4,5,6,7,8,9,10};
int*ptr1=(int*)(&a+1);
int*ptr2=(int*)(*(a+1));
printf("%d %d",*(ptr1-1),*(ptr2-1));
}
大家可以先在草稿纸上计算一下,然后运行一下看看是否和自己想的相同。
ptr1:对于ptr1取出的是整个数组的地址+1,指向10后面那个数字,在输出的过程中-1,向后退回了一位指向10这个元素,所以输出结果为10
ptr2:对于ptr2,数组名为首元素地址(第一行元素地址),+1后指向第二行首元素,在输出的过程中进行-1,指向5这个元素。
输出结果如下:
例题二
#include<stdio.h>
int main ()
{
char*a[]={"work","at","guge"};
char**pa=a;
pa++;
printf("%s\n",*pa);
}
大家还是先思考一下啊。
(如果个别编译器报错的话,在char的前面加上const,常量字符串不能修改)
这个题相对简单,a为数组名,pa取到的是a首元素的地址work,对pa进行++操作,pa此时指向的为at,输出后结果便是at
这里有一道之前的习题,不知道大家还记不记得,让我们一起来复习一下
#include<stdio.h>
int main ()
{
char str1[]="hello world.";
char str2[]="hello world.";
const char *str3="hello world.";
const char *str4="hello world.";
if(str1==str2)//数组名为首元素地址,但是两块空间不相同
printf("相同");
else
printf("不同");
if(str3==str4)//常量字符串无法修改,编译器在处理时只会存一份空间
printf("相同");
else
printf("不同");
}
代码中有解释,大家看看啊。
例题三(这个题比较难,做好心理准备)(对于我个人)
#include<stdio.h> int main () { const char*c[]={"steam","uplay","ubisoft","connect"}; const char**cp[]={c+3,c+2,c+1,c}; const char*** cpp=cp; printf("%s\n",**++cpp) ; //++让指向的地址改变了,再次解引用找到 *c的,解引用两次 printf("%s\n",*--*++cpp+3) ; //记得上次cpp++已经使cpp指向的不是cp收地址了,先进行++ // 因为这次已经解引用了, //--操作的对象为cp中的地址,对地址内容进行--,c+1变为c printf("%s\n",*cpp[-2]+3) ; //cpp[-2]的转化过来为 *(cpp-2), //再加上前面那个 *,整体为 **(cpp-2)+3, //字符串从第三个字符后开始从输出 . printf("%s\n",cpp[-1][-1]+1) ; //上面表达式分布进行分解 //第一次为 *(cpp-1)[-1] // 第二次为 *(*(cpp-1)-1)+1 }
大家先不要看注释,先自己尝试写一写。
1.对于**++cpp
输出结果为ubisoft
2.对于*--*++cpp+3
记得之前cpp已经++过了,此时cpp应该从c+2开始,再次++后指向c+1,此时解引用,对c+1这个地址的内容进行--,此时c+1变为c,再次解引用,指向c,此时+3表示从字符串的第三个开始输出。
输出结果为am
3.对于 *cpp[-2]+3
注意:先一步一步分析,cpp[-2]的含义为*(cpp-2)
此时指向connect,之后+3表示从第二个n开始输出,输出结果为nect
4.对于cpp[-1][-1]+1
总体来说,相当两个3的合集
先一步一步来,第一步*(cpp-1)[-1]+1
第二步为*(*(cpp-1)-1)+1
此时这个式子就简单了很多。
这里因为比较复杂分开来画图。
此时还剩余一个+1我们没有处理
综上,输出结果为play
PS:以上是本人学习指针中个人困惑过的地方,学习C语言的时间还较短,希望各位多多包涵,还有第一次使用Windows的画图工具,有点手残,希望大家能原谅。
看到最后一个输出结果大家也去playplay吧,学习C语言也要注意保护自己头发啊doge