学习完指针的相关知识点后,为了加深老铁们关于指针的理解,一起来拿这些试题练练手把!毕竟实践是检验真理的唯一标准!理论知识再6,也得学会实际运用才行,这些试题刚开始你可能觉得简单或困难,无论如何都得静下心来,理解其中的奥义,相信你可以收获关于指针的新的理解!最后那一句老梗激励我们继续学习吧!Practice makes perfect——熟能生巧!!
目录
2-2-1 代码1(sizeof操作符)----结尾无具体 \0字符
2-2-2 代码2(strlen函数)----结尾无具体 \0字符
2-2-3 代码3(sizeof操作符)----结尾有具体 \0字符
2-2-4 代码4(strlen函数)----结尾有具体 \0字符
2-2-5 代码5(sizeof操作符)----字符指针变量的应用
2-2-6 代码6(strlen函数)----字符指针变量的应用
1、sizeof与strlen的对比
1-1 sizeof操作符
在学习操作符的时候,我们学习了sizeof操作符,sizeof操作符是计算变量所占内存空间的大小的,单位是字节,如果操作数是类型的话,计算的是使用该类型创建的变量所占内存空间的大小。
sizeof只关注占用内存空间的大小,不关注内存中存放什么数据。
实例代码:
#inculde <stdio.h>int main(){int a = 10;printf("%d\n", sizeof(a));printf("%d\n", sizeof a);printf("%d\n", sizeof(int));return 0;}
输出结果:
输出结果为什么是这个呢?看完解析相信你就懂了!!
完整代码解析:
//sizeof操作符
#include <stdio.h>
int main()
{
int a = 10;
printf("%d\n", sizeof(a));//4--sizeof操作符计算大小不管具体数据只管是什么类型
printf("%d\n", sizeof a);//4--括号可以省略
printf("%d\n", sizeof(int));
return 0;
}
1-2 strlen函数
strlen是C语言库函数,功能是求字符串长度。
函数原型:
函数功能:统计的是从strlen函数的参数str中这个地址开始向后,\0之前字符串中字符的个数,
strlen函数会一直向后找\0字符,知道找到为止,所以可能会存在越界访问。
关于具体的strlen函数的使用和其他的字符函数与字符串函数使用,请看上一篇博客学习
实例代码:
#include <stdio.h>int main(){char arr1[3] = {'a', 'b', 'c'};char arr2[] = "abc";printf("%d\n", strlen(arr1));printf("%d\n", strlen(arr2));printf("%d\n", sizeof(arr1));printf("%d\n", sizeof(arr2));return 0;}

完整代码解析:
//strlen函数
#include <stdio.h>
int main()
{
char arr1[3] = { 'a', 'b', 'c' };//数组内容是 a b c
char arr2[] = "abcd";//内容a b c d \0
printf("%d\n", strlen(arr1));//随机值--不会遇到\0,会一直向后访问知道遇到\0,会产生越界访问的问题
printf("%d\n", strlen(arr2));//4--遇到\0就停下来计算\0之前字符的个数
printf("%d\n", sizeof(arr1));// 3
printf("%d\n", sizeof(arr2));// 5
return 0;
}
1-3 sizeof与strlen的对比
sizeof | 1、sizeof是操作符 |
2、sizeof计算操作数所占内存的大小,单位是字节。 | |
3、不关注内存中存放什么数据 | |
strlen | 1、strlen是库函数,使用需要引用头文件,<string.h> |
2、关注内存中是否有\0,如果没有\0,就会持续往后找,可能会越界 | |
3、strlen是求字符串长度的,统计的是\0之前字符的个数 |
2、数组与指针经典笔试题
2-0 储备知识
数组名的理解
1、数组名是数组首元素(第一个元素)的地址,但有两个例外
(1)sizeof(数组名)--数组名表示整个数组,计算的是整个数组的大小!单位是字节。数组名必须单独放在sizeof内部才是这种情况,否则不是!
(2)&数组名--数组名表示整个数组,取出的是整个数组的地址!——无需只存在&与数组名
除此之外,数组名就是数组首元素(第一个元素)的地址
2-1 一维数组
#include<stdio.h>
int main()
{
int a[] = {1,2,3,4};//数组有几个元素?printf("%d\n",sizeof(a));printf("%d\n",sizeof(a+0));printf("%d\n",sizeof(*a));printf("%d\n",sizeof(a+1));printf("%d\n",sizeof(a[1]));printf("%d\n",sizeof(&a));printf("%d\n",sizeof(*&a));printf("%d\n",sizeof(&a+1));printf("%d\n",sizeof(&a[0]));printf("%d\n",sizeof(&a[0]+1));return 0;
}
输出结果:
输出结果为什么是这个呢?看完解析相信你就懂了!!
分析:想知道输出结果我们得先知道数组名的理解——数组名是首元素的地址,但有两个例外,和int * 的理解——解引用访问的是整型,char * 理解——解引用访问的是字符型,至于为什么输出结果是这个请看下面的解析把老铁们!!
完整代码解析:
一维数组
#include<stdio.h>
int main()
{
int a[] = { 1,2,3,4 };
printf("%d\n", sizeof(a));// 16--sizeof(数组名)的场景,sizeof(数组名)计算的是整个数组的大小
printf("%d\n", sizeof(a + 0));// 4/8--a是首元素的地址,类型是int * ,a+0还是首元素的地址,是地址的话大小就是4/8个字节
printf("%d\n", sizeof(*a));// 4--a是首元素的地址,*a就是首元素,大小是4个字节。计算的是整型数组的第一个元素内存大小是4个字节
//*a==a[0]==*(a+0)
printf("%d\n", sizeof(a + 1));// 4/8--a是首元素的地址,类型是int *,a+1跳过1个整型,a+1就是第二个元素的地址,是地址的话大小就是4/8个字节
printf("%d\n", sizeof(a[1]));// 4--a[1]就是第二个元素,大小是4个字节
printf("%d\n", sizeof(&a));// 4/8--&a是取出整个数组的地址,数组的地址也是地址,是地址的话大小就是4/8个字节
printf("%d\n", sizeof(*&a));// 16--理解1、&*互相抵消了,sizeof(*&a)==sizeof(a)。连续使用&操作符与*操作符,两操作符的作用相互抵消,相当于没有使用操作符sizeof(数组名)计算的是整个数组的大小-16
//理解2、&a是取出整个数组的地址,类型是int (*)[4],对数组指针解引用访问的就是数组,转变为sizeof(数组名)的情况,那么计算的就是整个数组的大小-16
printf("%d\n", sizeof(&a + 1));// 4/8--&a+1是跳过整个数组后的那个位置的地址,是地址的话大小就是4/8个字节
printf("%d\n", sizeof(&a[0]));// 4/8--首元素的地址,是地址的话大小就是4/8个字节
printf("%d\n", sizeof(&a[0] + 1));// 4/8--&a[0]+1是数组第二个元素的地址,是地址的话大小就是4/8个字节
return 0;
}
2-1-1 小结时刻
- &a+1的类型是int(*)[4],a+1的类型是int *
- 数组名是首元素的地址,但有两个例外( sizeof(数组名)和&数组名)。具体内容请看前文!
- *&a有两种理解:理解1、&*互相抵消了,sizeof(*&a)==sizeof(a)。连续使用&操作符与*操作符,两操作符的作用相互抵消,相当于没有使用操作符sizeof(数组名)计算的是整个数组的大小。理解2、&a是取出整个数组的地址,类型是int (*)[4],对数组指针解引用访问的就是数组,转变为sizeof(数组名)的情况,那么计算的就是整个数组的大小
- *a==a[0]==*(a+0)
- sizeof操作符是计算类型所占内存空间的大小,不在乎内存中存放什么数据!!
- 指针+-整数跳过的是若干个指针指向对象的类型!
- 地址是有大小的,在不同的平台上对象不同,32位平台--4个字节;64位平台--8个字节!
2-2 字符数组
2-2-1 代码1(sizeof操作符)----结尾无具体 \0字符
#include<stdio.h>
int main()
{
char arr[] = {'a','b','c','d','e','f'};printf("%d\n", sizeof(arr));printf("%d\n", sizeof(arr+0));printf("%d\n", sizeof(*arr));printf("%d\n", sizeof(arr[1]));printf("%d\n", sizeof(&arr));printf("%d\n", sizeof(&arr+1));printf("%d\n", sizeof(&arr[0]+1));return 0;
}
输出结果:
输出结果为什么是这个呢?看完解析相信你就懂了!!
完整代码解析:
//字符数组
#include<stdio.h>
int main()
{
char arr[] = { 'a','b','c','d','e','f' };//数组内容a,b,c,d,e,f
printf("%d\n", sizeof(arr));// 6--数组名单独放在sizeof内部,计算的是整个数组的大小,单位是字节
printf("%d\n", sizeof(arr + 0));// 4/8--arr是数组名表示首元素的地址,arr+0还是首元素的地址,是地址的话大小就是4/8个字节
printf("%d\n", sizeof(*arr));// 1--arr是首元素的地址,*arr就是首元素,那么计算的是首元素的大小,大小是1个字节!
// *arr==arr[0]==*(arr+0)
printf("%d\n", sizeof(arr[1]));// 1--arr[1]是第二个元素,大小是1个字节
printf("%d\n", sizeof(&arr));// 4/8--&arr是取出整个数组的地址,数组的地址也是地址,是地址的话大小就是4/8个字节
printf("%d\n", sizeof(&arr + 1));// 4/8--&a+1是跳过整个数组后的那个位置的地址,即指向数组后面的空间,是地址的话大小就是4/8个字节
printf("%d\n", sizeof(&arr[0] + 1));// 4/8--&arr[0]+1是数组第二个元素的地址,是地址的话大小就是4/8个字节
return 0;
}
2-2-2 代码2(strlen函数)----结尾无具体 \0字符
#include<stdio.h>
int main()
{
char arr[] = {'a','b','c','d','e','f'};printf("%d\n", strlen(arr));printf("%d\n", strlen(arr+0));printf("%d\n", strlen(*arr));printf("%d\n", strlen(arr[1]));printf("%d\n", strlen(&arr));printf("%d\n", strlen(&arr+1));printf("%d\n", strlen(&arr[0]+1));return 0;
}
输出结果:
输出结果为什么是这个呢?看完解析相信你就懂了!!
完整代码解析:
#include<stdio.h>
int main()
{
char arr[] = { 'a','b','c','d','e','f' };//数组内容同理
printf("%d\n", strlen(arr));// 随机值--arr是数组首元素的地址,数组中没有\0,就会导致数组 越界访问,所以结果是随机值
printf("%d\n", strlen(arr + 0));// 随机值--arr+0是数组首元素的地址,数组中没有\0,就会导致数组越界访问,所以结果是随机值
//printf("%d\n", strlen(*arr));// err--arr是首元素的地址,*arr是首元素,就是‘a’,‘a’的ASCII码值是97,
//相当于将把97作为地址传给strlen函数,strlen函数得到的就是野指针,所以代码是有问题的!
//printf("%d\n", strlen(arr[1]));// err--arr[1]--‘b’--98,将98传给strlen函数也是错误的!
printf("%d\n", strlen(&arr));// 随机值--&arr是取出数组的地址,起始位置是数组第一个元素的位置,所以是随机值x
printf("%d\n", strlen(&arr + 1));// 随机值--同理,但随机值是x-6
printf("%d\n", strlen(&arr[0] + 1));// 随机值--是从第二个元素开始向后统计,得到的也是随机值 x-1
return 0;
}
2-2-3 代码3(sizeof操作符)----结尾有具体 \0字符
#include<stdio.h>
int main()
{
char arr[] = "abcdef";printf("%d\n", sizeof(arr));printf("%d\n", sizeof(arr+0));printf("%d\n", sizeof(*arr));printf("%d\n", sizeof(arr[1]));printf("%d\n", sizeof(&arr));printf("%d\n", sizeof(&arr+1));printf("%d\n", sizeof(&arr[0]+1));return 0;
}
输出结果:
输出结果为什么是这个呢?看完解析相信你就懂了!!
完整代码解析:
#include<stdio.h>
int main()
{
char arr[] = "abcdef";
printf("%d\n", sizeof(arr));// 7--arr是数组名,单独放在sizeof内部,计算的是整个数组的大小--7个字节
printf("%d\n", sizeof(arr + 0));// 4/8--arr表示首元素的地址,arr+0还是表示数组首元素的地址,是地址的话大小就是4/8个字节
printf("%d\n", sizeof(*arr));// 1--arr是数组首元素的地址,*arr是首元素,大小是1个字节
printf("%d\n", sizeof(arr[1]));// 1--arr[1]是数组第二个元素,大小是1个字节
printf("%d\n", sizeof(&arr));// 4/8--&arr是取出整个数组的地址,数组的地址也是地址,是地址的话大小就是4/8个字节
printf("%d\n", sizeof(&arr + 1));// 4/8--&arr+1是跳过整个数组后的那个位置的地址,
//(&arr是取出整个数组的地址,+1操作跳过整个数组,还是地址)即指向数组后面的空间,是地址的话大小就是4/8个字节
printf("%d\n", sizeof(&arr[0] + 1));// 4/8--&arr[0]+1是第二个元素的地址,是地址的话大小就是4/8个字节
return 0;
}
2-2-4 代码4(strlen函数)----结尾有具体 \0字符
#include<stdio.h>
int main()
{
char arr[] = "abcdef";printf("%d\n", strlen(arr));printf("%d\n", strlen(arr+0));printf("%d\n", strlen(*arr));printf("%d\n", strlen(arr[1]));printf("%d\n", strlen(&arr));printf("%d\n", strlen(&arr+1));printf("%d\n", strlen(&arr[0]+1));return 0;
}
输出结果:
输出结果为什么是这个呢?看完解析相信你就懂了!!
完整代码解析:
#include<stdio.h>
int main()
{
char arr[] = "abcdef";
printf("%d\n", strlen(arr));// 6--计算\0之前字符的个数
printf("%d\n", strlen(arr + 0));// 6--arr是首元素的地址,arr+0还是首元素的地址,向后在\0之前有6个字符
//printf("%d\n", strlen(*arr));// err--‘a’-97
//printf("%d\n", strlen(arr[1]));// err--‘b’-98
printf("%d\n", strlen(&arr));// 6--&arr是取出整个数组的地址,也是从数组的第一个元素开始向后找\0,
//计算\0之前的字符个数
//&arr--char(*)[7]
//size_t strlen(const char *s)
printf("%d\n", strlen(&arr + 1));// 随机值--取出的是指针变量的地址,所以结果是随机值
printf("%d\n", strlen(&arr[0] + 1));// 5--从数组的第二个元素开始向后找\0,计算\0之前的字符个数
return 0;
}
2-2-5 代码5(sizeof操作符)----字符指针变量的应用
#include<stdio.h>
int main()
{
char *p = "abcdef";printf("%d\n", sizeof(p));//p是指针变量,计算的是指针变量的大小,4/8个字节printf("%d\n", sizeof(p+1));printf("%d\n", sizeof(*p));printf("%d\n", sizeof(p[0]));printf("%d\n", sizeof(&p));printf("%d\n", sizeof(&p+1));printf("%d\n", sizeof(&p[0] + 1));return 0;
}
输出结果:
输出结果为什么是这个呢?看完解析相信你就懂了!!
完整代码解析:
#include<stdio.h>
int main()
{
const char* p = "abcdef";
printf("%d\n", sizeof(p));// 4/8--p是指针变量,计算的是指针变量的大小,即计算地址的大小,4/8个字节
printf("%d\n", sizeof(p + 1));// 4/8--p+1是字符'b'的地址,是地址的话大小就是4/8个字节
printf("%d\n", sizeof(*p));// 1--p的类型是const char *,*p就是char类型,大小就是1个字节
printf("%d\n", sizeof(p[0]));// 理解1、p[0]->*(p+0)->*p=='a',大小是1个字节
//理解2、把常量字符串想象成数组,p可以理解为数组名,那么p[0]就是首元素,大小是1个字节
printf("%d\n", sizeof(&p));// 4/8--取出p的地址,是地址的话大小就是4/8个字节
printf("%d\n", sizeof(&p + 1));// 4/8--&p是取出p的地址,+1是跳过p指针变量后的地址,是地址的话大小就是4/8个字节
printf("%d\n", sizeof(&p[0] + 1));// 4/8--&p[0]是取出字符串首字符的地址,+1操作是取出第二个字符的地址,
//是地址的话大小就是4/8个字节
return 0;
}
2-2-6 代码6(strlen函数)----字符指针变量的应用
#include<stdio.h>
int main()
{
char *p = "abcdef";printf("%d\n", strlen(p));printf("%d\n", strlen(p+1));printf("%d\n", strlen(*p));printf("%d\n", strlen(p[0]));printf("%d\n", strlen(&p));printf("%d\n", strlen(&p+1));printf("%d\n", strlen(&p[0]+1));return 0;
}
输出结果为什么是这个呢?看完解析相信你就懂了!!
输出结果:
完整代码解析:
#include<stdio.h>
int main()
{
char* p = "abcdef";
printf("%d\n", strlen(p));// 6--指针p指向首字符的地址,是计算\0之前字符的个数
printf("%d\n", strlen(p + 1));// 5--p+1是第二个字符的地址,是计算\0之前字符的个数
//printf("%d\n", strlen(*p));//err--‘a’-97
//printf("%d\n", strlen(p[0]));//err--p[0]==*(p+0)==*p。‘a’-97
printf("%d\n", strlen(&p));// 随机值--&p是指针变量p的地址和字符串的地址关系不大
//从p这个指针变量的起始位置开始向后数的,p变量存放的地址是什么,不知道。所以结果是随机值
printf("%d\n", strlen(&p + 1));// 随机值--取出的是指针变量的地址,所以结果是随机值
printf("%d\n", strlen(&p[0] + 1));// 5--取出字符串首字符的地址,+1含义是第二个字符的地址
return 0;
}
2-2-7 小结时刻
- 可以把常量字符串想象成数组
- p可以理解为数组名,那么p[0]就是首元素
- p[0]==*(p+0)==*p
- &p是指针变量p的地址和字符串的地址关系不大,从p这个指针变量的起始位置开始向后数的,p变量存放的地址是什么,不知道!
- 将字符对应的ASCII码值传给strlen函数,函数会将其当成地址,但找不到所以会报错!
- 对于sizeof(p[0])可以这样理解,理解1、p[0]->*(p+0)->*p=='a',大小是1个字节,理解2、把常量字符串想象成数组,p可以理解为数组名,那么p[0]就是首元素,大小是1个字节
- &p是取出p的地址,+1是跳过p指针变量后的地址
- &p[0]是取出字符串首字符的地址,+1操作是取出第二个字符的地址,是地址的话大小就是4/8个字节
2-3 二维数组
代码如下:
#include<stdio.h>
int main()
{
int a[3][4] = {0};printf("%d\n",sizeof(a));printf("%d\n",sizeof(a[0][0]) );printf("%d\n",sizeof(a[0]) );printf("%d\n",sizeof(a[0]+1) );printf("%d\n",sizeof( *( a[0]+1) ) );printf("%d\n",sizeof (a+1) );printf("%d\n",sizeof( * (a+1) ) );printf("%d\n",sizeof( &a[0]+1) );printf("%d\n",sizeof(* ( &a[0]+1 ) ) );printf("%d\n",sizeof( *a) );printf("%d\n",sizeof (a[3]) );rerurn 0;
}
输出结果:
再次强调一下,数组名的意义
1、数组名是数组首元素(第一个元素)的地址;
但有两个例外
(1)sizeof(数组名)--数组名表示整个数组,计算的是整个数组的大小!单位是字节。数组名必须单独放在sizeof内部才是这种情况,否则不是!
(2)&数组名--数组名表示整个数组,取出的是整个数组的地址!——无需只存在&与数组名
除此之外,数组名就是数组首元素(第一个元素)的地址!!
小伙伴们肯定会不理解为什么,输出结果是这个呢?那康康下面的解析把下,我相信看完后你一定有所收获!!
完整代码解析:
//二维数组
#include<stdio.h>
int main()
{
int a[3][4] = { 0 };
printf("%d\n", sizeof(a));// 48--a是数组名,单独放在sizeof内部,计算的是数组的大小,单位是字节--48=3*4*sizeof(int)
printf("%d\n", sizeof(a[0][0]));// 4--a[0][0]是第一行第一个元素,大小是4个字节
printf("%d\n", sizeof(a[0]));// 16--a[0]是第一行的数组名,数组名单独放在sizeof内部了,计算的是数组的总大小--16个字节
printf("%d\n", sizeof(a[0] + 1));// 4/8--a[0]是第一行的数组名,但a[0]没有单独放在sizeof内部,所以这里的数组名a[0]就是
//数组首元素的地址,就是&a[0][0],+1后就是a[0][1]的地址,大小是4/8个字节
printf("%d\n", sizeof(*(a[0] + 1)));//4--* ( a[0] + 1) 表示第一行第二个元素(访问的是第二行第一个元素),大小是4个字节
printf("%d\n", sizeof(a + 1));// 4/8--a作为数组名没有单独放在sizeof内部,所以这里的数组名a表示数组首元素的地址,
//是二维数组首元素的地址,就是第一行的地址,a+1含义跳过一行,指向第二行,a+1是第二行的地址,a+1是数组指针,
// 是地址的话大小就是4/8个字节!
printf("%d\n", sizeof(*(a + 1)));// 16--理解1、a+1是第二行的地址,*(a+1)是第二行,计算的是第二行的大小
//理解2、*(a+1)==a[1],a[1]是第二行的数组名,sizeof(*(a+1))==sizeof(a[1]),意思是把第二行的数组名单独放在sizeof内部,
//计算第二行的大小
printf("%d\n", sizeof(&a[0] + 1));// 4/8--a[0]是第一行的数组名,&a[0]取出的就是这个数组的地址,
//就是第一行的地址,&a[0]+1就是第二行的地址,是地址的话大小就是4/8个字节
printf("%d\n", sizeof(*(&a[0] + 1)));// 16--*(&a[0] + 1)意思是对第二行的地址进行解引用,访问的是第二行,大小是16个字节
printf("%d\n", sizeof(*a)); //16--a作为数组名没有单独放在sizeof内部,所以这里的数组名a表示数组首元素的地址,
//是二维数组首元素的地址,就是第一行的地址,*a就是第一行,计算的是第一行所有元素的大小--4*4=16
//*a==*(a+0)==a[0]
printf("%d\n", sizeof(a[3])); //16--a[3]无需真实存在,仅仅通过类型的推断就能算出长度,
//a[3]是第四行的数组名,单独放在sizeof内部,计算的是第四行的大小--16个字节
return 0;
}
2-3-1 小结时刻
- 数组名是首元素的地址,但有两个例外( sizeof(数组名)和&数组名)。具体内容请看前文!
- 对于a[0]可以这样理解,a[0]是第一行的数组名,数组名单独放在sizeof内部了,计算的是数组的总大小
- 对于sizeof(a[3])的理解要特别注意,a[3]无需真实存在,仅仅通过类型的推断就能算出长度,
- a[3]是第四行的数组名,单独放在sizeof内部,计算的是第四行的大小
- 对于sizeof(*(a+1))可以这样理解:理解1、a+1是第二行的地址,*(a+1)是第二行,计算的是第二行的大小 理解2、*(a+1)==a[1],a[1]是第二行的数组名,sizeof(*(a+1))==sizeof(a[1]),意思是把第二行的数组名单独放在sizeof内部,计算第二行的大小
- 对于sizeof(a+1)可以这样理解:a作为数组名没有单独放在sizeof内部,所以这里的数组名a表示数组首元素的地址,是二维数组首元素的地址,就是第一行的地址,a+1含义跳过一行,指向第二行,a+1是第二行的地址,a+1是数组指针,是地址的话大小就是4/8个字节!
- *a==*(a+0)==a[0]
3、指针运算经典笔试题
3-1 试题一----指针+-整数
#include <stdio.h>int main(){int a[5] = { 1, 2, 3, 4, 5 };int *ptr = (int *)(&a + 1);printf( "%d,%d", *(a + 1), *(ptr - 1));return 0;}//输出结果是什么呢?


3-2 试题二----指针+-整数
//假设该结构大小是20个字节
// 环境是:X86(32位)struct Test{int Num;char *pcName;short sDate;char cha[2];short sBa[4];}*p = (struct Test*)0x100000;int main(){printf("%p\n", p + 0x1);printf("%p\n", (unsigned long)p + 0x1);printf("%p\n", (unsigned int*)p + 0x1);return 0;}//输出结果是什么呢?

我们知道整型指针加1,跳过的是一个整型,那么结构体指针+1,跳过的就是一个结构体,
3-3 试题三----逗号表达式
#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;}//程序的结果是什么呢?


#include <stdio.h>
int main()
{
int a[3][2] = { (0, 1), (2, 3), (4, 5) };//初始化,逗号表达式
int* p;//1 3 5 0 0 0
p = a[0];
printf("%d", p[0]);
return 0;
}
3-4 试题四----指针-指针
#include <stdio.h>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;}//假设环境是x86环境,输出结果是什么?


#include <stdio.h>
int main()
{
int a[5][5];
int(*p)[4];//p是数组指针,p指向的数组是4个整型元素
p = a;
printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
return 0;
}
// 指针-指针的绝对值==指针与指针之间的元素个数!
3-5 试题五----指针+-整数
#include <stdio.h>int main(){int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };int *ptr1 = (int *)(&aa + 1);int *ptr2 = (int *)(*(aa + 1));printf( "%d,%d", *(ptr1 - 1), *(ptr2 - 1));return 0;}//输出的是什么呢?
输出结果:
输出结果为什么是这个呢?看完分析,相信你就懂了!!
分析与图解:
这里的*(aa+1)==aa[1] !
3-6 试题六----指针在二维数组的应用
#include <stdio.h>int main(){char *a[] = {"work","at","alibaba"};char**pa = a;pa++;printf("%s\n", *pa);return 0;}//输出结果是什么?

#include <stdio.h>
int main()
{
int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int* ptr1 = (int*)(&aa + 1);
int* ptr2 = (int*)(*(aa + 1));
printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));
return 0;// 10 5
}
//1, 2, 3, 4, 5, 6, 7, 8, 9, 10
3-7 试题七----指针在二维数组的应用
#include <stdio.h>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指向的位置+1,然后再访问相关的空间。即流程是cpp+1找到空间并访问,空间里存放c+2,然后再根据c+2找到存放point的空间
*-- * ++cpp +3,首先根据操作符的优先级,先将cpp在上一次的位置+1,然后再访问空间,空间里存放数值c+1,再将c+1变为c,再根据c访问相关的空间,可知空间里存放了字符'E'的地址,再+3指向的就是字符’e‘,即打印er
*cpp[-2] + 3,首先根据操作符的优先级,先将cpp在上一次的位置-2,然后再访问空间,空间里存放数值c+3,再根据c+3,访问相关的空间,可知空间里存放了字符‘F’的地址,再将其+3,那么就指向了字符‘s'!!
cpp[-1][-1]+1==*(*(cpp-1)-1)+1,首先根据操作符的优先级,先将cpp在上一次的位置-1,然后再访问空间,空间里存放数值c+2,再将c+2改变为c+1,再根据c+1,访问相关的空间,可知空间里存放了字符'N'的地址,再+1指向的就是字符’e‘,即打印ew
老铁们制作不易,一键三连吧!!!