指针典型笔试题练习+额外拓展

文章目录

例1

#include <stdio.h>
int main()
{
    
    
int a[3][2] = {
    
     (0, 1), (2, 3), (4, 5) };
int *p;
p = a[0];
printf( "%d", p[0]);
return 0;
}

注意分辨int a [3][2] = { {0,1},{2,3},{4,5}},这才是给数组初始化了3行2列
,而这里{}里是() , 说明它是一个逗号表达式,逗号表达式的结果为最后一个表达式结果,所以a中只放入了1,3,5,其余放0
a[0] 为第一行数组名,即首元素a[0][0]的地址,p[0] 即*(p +0)即对&a[0][0] 解引用,得到1

例2

int main()
{
    
    
int a[5][5];
int(*p)[4];
p = a;
printf( "%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
return 0;
}

a为首元素地址,即第一行的地址,将第一行的地址放入p中,第一行的地址类型为int(*)[5],p的类型为int( * )[4],但是p是一个指针变量,所以可以存a的地址,但当p+1时跳过4个整形,p[4] 即为
*(p + 4),对数组指针解引用可以理解为得到的是数组名,因为p指向的是一个有4个元素的整形数组指针,所以p[4]这个数组有4个元素,p[4][2],数组名[2],即为该数组的下标为2的元素

在这里插入图片描述
橙色的为&p[4][2],蓝色的为&a[4][2],指针-指针的绝对值得到的是两者之间的元素个数,这里小地址-大地址得到-4,以%p的形式打印-4,内存中存的是-4的补码,所以会将补码直接以16进制打印
%d打印会打印-4

例3

int main()
{
    
    
char *c[] = {
    
    "ENTER","NEW","POINT","FIRST"};
char**cp[] = {
    
    c+3,c+2,c+1,c};
char***cpp = cp;
printf("%s\n", **++cpp);
printf("%s\n", *--*++cpp+3);
printf("%s\n", *cpp[-2]+3);
printf("%s\n", cpp[-1][-1]+1);
return 0;
}

开始时,各变量对应的位置
在这里插入图片描述

在这里插入图片描述

对于第一个打印,++cpp,cpp指向c+2,*cpp拿到c+2, * *cpp即 * (c+2),拿到p的地址,
从p的地址以%s向后打印,即打印POINT
在这里插入图片描述

对于第二个打印,值得注意的是此时cpp由于上一次的打印,cpp已经变了,指向了c+2,计算时要额外注意,因为cpp左边的++优先级更高,所以先算++cpp,cpp指向了c+1,解引用得到c+1,再进行- -,得到c,再次解引用得到E的地址,+3,跳过3个字符,得到第二个E的地址,打印ER
在这里插入图片描述

对于第三个打印,对于cpp[-2]即为* (cpp - 2),cpp-2指向了c+3,解引用得到c+3,再次解引用得到F的地址,+3得到S的地址,打印ST
在这里插入图片描述

对于第四个打印,我们可以 * ((cpp-1) - 1) +1, (cpp -1)得到c+2,再-1得到c+1,再次解引用得到N的地址,+1得到E的地址,打印EW

额外拓展

对于创建的变量,我们有两层理解方式, 对于 int a = 0;
a = 10,这里对于a的理解为a是一块空间可以存放20,所以这里a是左值
对于a + 10,这里对于a的理解为a是一个值,这里a是右值
对于a++,我们使用的是左值,因为10++这种方式是不可行的

猜你喜欢

转载自blog.csdn.net/wan__xia/article/details/129650960
今日推荐