这几十道指针与数组结合的题目,你能做对几题?

简介: 这几十道指针与数组结合的题目,你能做对几题?

在这里插入图片描述

请点下面链接:

-> 给大家推荐一款很火爆的刷题、面试求职网站 <-

前言

很多时候我们以为学会了理论知识,就好像学了C语言的指针,但是感觉啥也不懂,所谓“一学就会,一做就废”,相信大家都有所感受!
其实所谓以为,讲实了,就是自己以为,本质还是不理解(狗头保命doge
==“实践是检验唯一的标椎”==,不会?练就完事了!

所以这次给大家分享几十道指针和数组(含二维数组)

目录

  1. 预备知识
  2. 开胃小菜
  3. 提升难度
  4. 问题延伸
  5. 再作延伸
  6. 最后一击(压轴)

正文

预备知识
我们知道 <font color=#ff33 size=3 face=“黑体”>数组名表示首元素地址</font>      但有两种情况是例外的
    

1.sizeof(数组名) ---数组名表示整个数组

2.&数组名 --- 表示整个元素的地址


<font color=#ff33 size=4 face=“黑体”>函数strlen</font> 计算字符串长度,只有在遇到    <font color=#ff33 size=4 face=“黑体”>'\0'</font> 才停止计算个数     

而且它的参数是一个 字符指针 strlen( const char*string )

开胃小菜

下面程序输出什么?

//一维数组
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));
在这里插入图片描述

详解:

//一维数组
    int a[] = { 1,2,3,4 };
    printf("%d\n", sizeof(a));
     // 16 数组名单独放在sizeof()里面,所以数组名表示整个数组的大小4*4

    printf("%d\n", sizeof(a + 0));
    // 4/8 数组名不是单独放在sizeof里面,所以数组名表示首元素地址,
    //首元素地址+1还是首元素地址,是地址在32位平台就4个字节,64位平台就8个字节

    printf("%d\n", sizeof(*a));
    // 4  同样数组名不是单独放在sizeof里面,所以还是首元素地址,首元素地址解引用(*),
    //就是首元素,因为数组是int类型,所以为4

    printf("%d\n", sizeof(a + 1));
    // 4/8 跟sizeof(a+0)同样的道理,只不过这个指针指向的是数组第二个元素

    printf("%d\n", sizeof(a[1]));// 4  a[1]就是第二个元素,而且a[1]=*(a+1)

    printf("%d\n", sizeof(&a));    
     // 4/8 &数组名,表示整个元素的地址,是地址就是4或8个字节
    //(千万不要因为它是整个元素地址就认为跟其他地址不一样)

    printf("%d\n", sizeof(*&a));    
    // 16 首先&数组名,就是整个数组的地址,而解引用(*)之后就是整个数组
    //注释:其实 * 与 & 相当于一个互逆运算,可以理解成两个抵消了变成sizeof(a)
                                        
    printf("%d\n", sizeof(&a + 1));
     // 4/8 &数组名就是整个数组的地址,&a+1就是跳过整个数组后的地址,
     //不管怎样都是地址

    printf("%d\n", sizeof(&a[0]));
        // 4/8  a[0]为首元素,&a[0]就是首元素地址
    printf("%d\n", sizeof(&a[0] + 1));
    // 4/8  &a[0]为首元素地址,+1后就为第二个元素的地址
    

提升难度
//字符数组
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));
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));
在这里插入图片描述
    //字符数组
    char arr[] = { 'a','b','c','d','e','f' };
    printf("%d\n", sizeof(arr));
     // 6  数组名单独放在sizeof里面,数组名就表示整个数组,数组的大小就为1*6=6
    printf("%d\n", sizeof(arr + 0));
    // 4/8  数组名不是单独放在sizeof里面,所以它是首元素地址,+0也是首元素地址

    printf("%d\n", sizeof(*arr));
     // 1 同样数组名不是单独放在sizeof里面,所以数组名表示首元素地址,
     //解引用(*)后就为首元素而数组是char类型的,所以为1字节
                                    
    printf("%d\n", sizeof(arr[1]));// 1  arr[1]就为第二个元素
    printf("%d\n", sizeof(&arr));    
    // 4/8 &数组名 表示整个数组的地址,是地址就是4或8个字节
    
    printf("%d\n", sizeof(&arr + 1));
    // 4/8  数组的地址+1,也是地址
    printf("%d\n", sizeof(&arr[0] + 1));
    // 4/8  &arr[0] 就是首元素地址,+1后就是第二个元素的地址,是地址就是4/8个字节
    printf("%d\n", strlen(arr));
    // 随机值 因为数组{'a','b'}类型于这样的初始化方式,
    //它在结尾都没有'\0',所以无法知道strlen在什么时候遇到'\0'停止计算
                                
    printf("%d\n", strlen(arr + 0));
    //随机值 arr+0,为首元素地址,+0也为首元素地址,但是也是跟上面一样
    
    printf("%d\n", strlen(*arr));
    // err(错误)  strlen的参数是传一个字符指针,但是*arr为首元素,也就是'a'
    //a的ascll为97,你硬要传过去的话,那么strlen就认为它是一个地址,而97的地址
    //不是我们开辟的,对它进行访问的话,就是越界访问了程序错误
    
    printf("%d\n", strlen(arr[1]));
    //err(错误) arr[1]是第二个元素,也就是'b',跟上面一样的错误
    
    printf("%d\n", strlen(&arr));
    // 随机值 &arr 为整个数组的地址,但数组的地址其实数值上跟首元素的地址是一样的,
    //'\0'位置同样无法确定
    
    printf("%d\n", strlen(&arr + 1));
    // 随机值-6  &arr+1 越个一个数组后的地址,也是无法确定'\0'位置,但是它跟上面的
    //那个随机值有一定的联系, 那就是比它小6,随机值-6

    printf("%d\n", strlen(&arr[0] + 1));
    // 随机值-1  &arr[0]首元素地址,+1后就是第二个元素的地址,但是也不知道'\0'的位置


问题延伸

下列程序输出什么


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));
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));
在这里插入图片描述

详解:

    char arr[] = "abcdef";
 //这种初始化方式后面个默认有个'\0',也就是说这个数组的内容为abcdef\0
 
    printf("%d\n", sizeof(arr));
     //7  数组的内容为abcdef\0,数组名单独放在sizeof里面,
     //所以表示整个数组的大小,也就是7*1
     
    printf("%d\n", sizeof(arr + 0));
    //4/8 数组名不是单独放在sizeof里面,所以这里的数组名表示首元素地址
    //,+0也为首元素地址是地址就为4或8个字节
                                    
    printf("%d\n", sizeof(*arr));
    // 1 同样,数组名不是单独放在sizeof里面,所以数组名表示首元素地址,
    //解引用(*)后就是首元素a,char类型为1个字节
    
    printf("%d\n", sizeof(arr[1]));
    // 1 arr[1]为第二个元素b,也等同于*(arr+1)
    
    printf("%d\n", sizeof(&arr));    
    // 4/8 &arr,表示整个数组的地址,是地址就为4或8个字节
    
    printf("%d\n", sizeof(&arr + 1));
    // 4/8 数组的地址+1,就是跳过一个数组后的地址,是地址就为4或8个字节
    
    printf("%d\n", sizeof(&arr[0] + 1));
    //4/8 &arr[0],首元素地址,+1后就为第二个元素的地址
    
    printf("%d\n", strlen(arr));
    //6  数组的内容为abcdef\0,arr表示首元素地址,从第一个元素开始算个数到\0停止
    
    printf("%d\n", strlen(arr + 0));
    // 6  arr表示首元素地址,+0也为首元素地址
    
    printf("%d\n", strlen(*arr));    
     // err(错误)  strlen的参数是传一个字符指针,但是*arr为首元素,也就是'a'
    //a的ascll为97,你硬要传过去的话,那么strlen就认为它是一个地址,而97的地址
    //不是我们开辟的,对它进行访问的话,就是越界访问了,程序错误
    
    printf("%d\n", strlen(arr[1]));//err 同上
    
    printf("%d\n", strlen(&arr));
    // 6 &arr 为整个数组的地址,但在数值上跟首元素地址一样,
    //所以还从第一个元素开始算,遇\0停止
    printf("%d\n", strlen(&arr + 1));
    // 随机值 &arr 是整个数组的地址,+1后就是跳个整个数组的地址,
    //而我们知道strlen是遇到 '\0'才停止计算的,而你把arr数组的内容跳过了,
    //后面就不知道什么时候能遇到\0了
    printf("%d\n", strlen(&arr[0] + 1));
    //5 &arr[0]+1 是第二个元素的地址,也就是从第二个元素开始算,所以为6-1=5
    

再作延伸

下面输出什么?

char *p = "abcdef";
printf("%d\n", sizeof(p));
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));
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));
在这里插入图片描述

详解:

char* p = "abcdef"; 
     /*很多以为这是把abcdef存在指针p中,其实这是错误的想法,
            它的本质是把首元素的地址存放在p中,
            这也就是把a的地址存放在p中*/
            
    printf("%d\n", sizeof(p));
    //4/8  p是一个char类型的指针,存放的是元素a的地址
    
    printf("%d\n", sizeof(p + 1));
    //4 p+1为b的地址,是地址就为4或8个字节
    
    printf("%d\n", sizeof(*p));
    // 1  p为a的地址,解引用(*)就是a,a是char类型
    
    printf("%d\n", sizeof(p[0]));
    // 1 p[0]就是首元素a
    printf("%d\n", sizeof(&p));
    // 4/8  p是char*类型的指针,而&p,就是p的地址,char**,二级指针,
    //本质还是指针,还是4或8个字节
    
    printf("%d\n", sizeof(&p + 1));
    // 4/8 &p是p的地址,&p+1就是p地址的后一个地址,还是地址就是4或8个字节
    
    printf("%d\n", sizeof(&p[0] + 1));
    // 4/8  p[0]是元素a,&a[0]就是首元素地址,+1就是等二个元素的地址(b的地址)

    printf("%d\n", strlen(p));
    // 6  p为首元素a的地址,从a开始往后算个数就是6个字符
    //("abcdef"这样的初始化内存足够的情况下默认后面加\0)strlen遇\0停止计算
    
    printf("%d\n", strlen(p + 1));
    // 5 p为首元素地址,+1后为b的地址,往后数到\0后停止计算
    
    printf("%d\n", strlen(*p));
     // err(错误)  strlen的参数是传一个字符指针,但是*p为首元素,也就是'a'
    //a的ascll为97,你硬要传过去的话,那么strlen就认为它是一个地址,而97的地址
    //不是我们开辟的,对它进行访问的话,就是越界访问了程序错误
    
    printf("%d\n", strlen(p[0]));// err 同上
    
    printf("%d\n", strlen(&p));
    // 随机值 p是char*类型的指针,&p就是取去p的地址,&p的类型就是char**二级指针,
    //你把它传给strlen,也就是传了p的地址,它跟a的地址没什么联系,
    //&p指向的内容也不知道什么地方会出现\0
    
    printf("%d\n", strlen(&p + 1));
    // 随机值,也是p的地址,+1后就是跳过p的地址的后一个地址,也是不知道\0的
    //具体位置,它跟上面那个随机值没有任何关系,因为不知道它们之间是否存在\0
    
    printf("%d\n", strlen(&p[0] + 1));
    //5  p[0]为首元素a,&a[0]就是把a的地址取出来,+1就是b的地址,从b往后数就是5

最后一击(压轴)

最后的压轴是二维数组啦!

下面输出结果是什么?

//二维数组
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]));
在这里插入图片描述

详解:

    //二维数组
    int a[3][4] = { 0 };
    printf("%d\n", sizeof(a));
    //48  数组名单独放在sizeof里面,所以数组名表示整个数组大小,3*4*4=48
    
    printf("%d\n", sizeof(a[0][0]));
    //4,a[0][0]表示首元素,因为是int类型,所以为4

    printf("%d\n", sizeof(a[0]));
    //16 a[0] 是首元素,对于二维数组来说 它的首元素为第一行的,a[0]其实相当于第一行
    // 的名称,相当于sizeof(第一行名称),表示整个数组的大小, 第一行有4个元素,所以
    //结果为 4*4   a[0]表示第一行,a[1]表示第二行....

    printf("%d\n", sizeof(a[0] + 1));
    //4/8  上面讲了,a[0]本质是第一行的名称,sizeof里面表示单独放数组名,
    //所以表示该数组的首元素地址,而第一行的首元素地址+1就是第一行第二个元素的地址

    printf("%d\n", sizeof(*(a[0] + 1)));
    //4  a[0]+1就是第一行第二个元素的地址,解引用就是该地址对应的元素值等同于a[0][1]

    printf("%d\n", sizeof(a + 1)); 
    //4/8 数组名不是单独放在sizeof里面,所以a表示二维数组首元素地址,对于二维数组来说 
    //它的首元素为第一行的地址,+1就是第二行地址
                                    
    printf("%d\n", sizeof(*(a + 1)));
    // 16  a+1为第二行地址,它是单独放在sizeof里面,所以表示整个数组大小
                                        
    printf("%d\n", sizeof(&a[0] + 1));
    //4/8 a[0]是第一行,&a[0]就是把整个数组的地址取出来,+1就是跳过整个数组指向
    //下一个数组,也就是指向第二行,本质还是数组
                                        
    printf("%d\n", sizeof(*(&a[0] + 1)));
    // 16  &a[0]+1是第二行地址,解引用(*)后就拿到第二行数组的名称,sizeof()
    //里面单独放数组名,表示整个数组的大小

    printf("%d\n", sizeof(*a));
    //16  数组名不是单独放在sizeof里面,所以表示二维数组的首元素地址,
    //二维数组的首元素地址就是第一行地址,解引用(*)后相当于sizeof(第一行名称),
    //数组名单独放里,所以是整个第一行数组的大小
    
    printf("%d\n", sizeof(a[3]));
    //16  a[3]相当于第四行地址,虽然这里没有第四行,但不影响它单独放在sizeof里面,
    //所以表示整个数组的大小,这个数组跟a[0],a[1]哪些是一样的道理,都是4个元素

总结

如果你能无压力的做出上面的几十道题,那么我想你对指针的理解已经很深刻了!

当然如果刚开始有点吃力,看完答案后你能完全理解,那也是很强的!!

最后给大家复习一下重点

1. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。
2. &数组名,这里的数组名表示整个数组,取出的是整个数组的地址。
3. 除此之外所有的数组名都表示首元素的地址。

这次的题目分享就到此结束吧!

相关文章
|
25天前
使用指针访问数组元素
【10月更文挑战第30天】使用指针访问数组元素。
31 3
|
24天前
使用指针访问数组元素
【10月更文挑战第31天】使用指针访问数组元素。
32 2
|
1月前
|
算法 索引
单链表题+数组题(快慢指针和左右指针)
单链表题+数组题(快慢指针和左右指针)
34 1
|
2月前
|
存储
如何使用指针数组来实现动态二维数组
指针数组可以用来实现动态二维数组。首先,定义一个指向指针的指针变量,并使用 `malloc` 为它分配内存,然后为每个子数组分配内存。通过这种方式,可以灵活地创建和管理不同大小的二维数组。
|
2月前
|
存储
如何通过指针数组来实现二维数组?
介绍了二维数组和指针数组的概念及其区别,详细讲解了如何使用指针数组模拟二维数组,包括定义与分配内存、访问和赋值元素、以及正确释放内存的步骤,适用于需要动态处理二维数据的场景。
|
2月前
|
存储 算法 C语言
C语言:什么是指针数组,它有什么用
指针数组是C语言中一种特殊的数据结构,每个元素都是一个指针。它用于存储多个内存地址,方便对多个变量或数组进行操作,常用于字符串处理、动态内存分配等场景。
|
2月前
魔法指针 之 二级指针 指针数组
魔法指针 之 二级指针 指针数组
19 1
|
2月前
|
存储
一篇文章了解区分指针数组,数组指针,函数指针,链表。
一篇文章了解区分指针数组,数组指针,函数指针,链表。
19 0
|
2月前
|
编译器 C语言
【C语言】指针篇-深入探索数组名和指针数组- 必读指南(2/5)
【C语言】指针篇-深入探索数组名和指针数组- 必读指南(2/5)