c语言进阶(3)——指针进阶笔试题详解

1.指针和数组笔试题解析

关键:数组名在两种情况下是指整个数组:
(1)sizeof(数组名)(2)&数组名
其它的情况下,都是代表数组的首元素地址。

例题 1 :一维数组

int main()
{
//一维数组
int a[] = { 1,2,3,4 };

printf("%d\n", sizeof(a));
//此时的表达式只是数组名a,代表的是整个数组,sizeof计算的是整个数组的大小,为4*4=16个字节。

printf("%d\n", sizeof(a + 0));
//a+0是表达式,数组名a代表的是数组的首元素地址,为int型指针变量,
//+0后还是int型指针变量,大小是4/8个字节。

printf("%d\n", sizeof(*a));
//*a不是单纯的数组名,a表示的首元素的地址,解引用后为int整数1,其大小是4个字节。

printf("%d\n", sizeof(a + 1));
//a+1是表达式,数组名a表示的是首元素的地址,为int型指针变量,
//+1后还是int型指针变量,大小是4/8个字节。

printf("%d\n", sizeof(a[1]));
//a[1]表示的整型2,为int变量,其大小是4个字节

printf("%d\n", sizeof(&a));
//此时的数组名a表示的整个数组,&a后表示的数组指针,是指针,占4/8个字节

printf("%d\n", sizeof(*&a));
//此时的数组名a表示的是整个数组,&a后解引用后是数组名a,此时单纯的数组a,表示的整个数组
//其大小是4*4=16个字节

printf("%d\n", sizeof(&a + 1));
//&a是整个数组的地址,+1后还是表示地址,是地址,其大小是4/8

printf("%d\n", sizeof(&a[0]));
//数组首元素取地址,是地址,其大小是4/8

printf("%d\n", sizeof(&a[0] + 1));
//数组首元素取地址后+1还是表示地址,是地址,其大小是4/8。

return 0;

}

例题 2 :字符数组

int main()
{
//字符数组
char arr[] = { ‘a’,‘b’,‘c’,‘d’,‘e’,‘f’ };

printf("%d\n", sizeof(arr));
//数组名表示这个数组,计算的整个数组的大小,为1*6=6

printf("%d\n", sizeof(arr + 0));
//此时为表达式,数组名表示的首元素的地址,+0之后还是地址,是地址,其大小为4/8

printf("%d\n", sizeof(*arr));
//数组名arr此时为数组首元素,解引用后为字符‘a’,其大小为1个字节

printf("%d\n", sizeof(arr[1]));
//此时计算的数组第二元素‘b’,其大小为1个字节

printf("%d\n", sizeof(&arr));
//此时数组名为整个数组,&arr 代表是数组指针,是指针,是地址,其大小为4/8

printf("%d\n", sizeof(&arr + 1));
//此时数组名为整个数组,&arr代表的是数组指针,加一后还是指针,是地址,其大小为4/8个字节

printf("%d\n", sizeof(&arr[0] + 1));
//&a[0]是char*类型的指针,加一后还是指针,是地址,其大小为4/8个字节。

return 0;

}
#include<string.h>
int main()
{
char arr[] = { ‘a’,‘b’,‘c’,‘d’,‘e’,‘f’ };

printf("%d\n", strlen(arr));
//此时的数组名是首元素的地址,但是该数组没有以'\0'结尾,所得的值是随机的

printf("%d\n", strlen(arr + 0));
//同上

printf("%d\n", strlen(*arr));
//此时的数组名是首元素的地址,解引用后是‘a’->97 ,此时非法访问地址97,error

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;

}

int main()
{
char* p = “abcdef”;

printf("%d\n", sizeof(p));
//p是一个char *类型的指针,是地址,其大小为4/8个字节

printf("%d\n", sizeof(p + 1));
//同上

printf("%d\n", sizeof(*p));
//p指向的是字符串的首元素a的地址,解引用后得到字符a,其大小为1个字节。

printf("%d\n", sizeof(p[0]));
//同上

printf("%d\n", sizeof(&p));
//&p是得到变量p的地址,是二级指针,是地址,其大小为4/8

printf("%d\n", sizeof(&p + 1));
//同上

printf("%d\n", sizeof(&p[0] + 1));
//&p[0]得到的是字符a的地址,加一后还是地址,是地址,其大小为4/8

printf("%d\n", strlen(p));
//得到整个字符串的长度6

printf("%d\n", strlen(p + 1));
//得到5

printf("%d\n", strlen(*p));
//*p得到字符‘a’==97,非法访问  error

printf("%d\n", strlen(p[0]));
//同上

printf("%d\n", strlen(&p));
//&p得到的是变量p的地址,不知道结束符在哪,是随机值

printf("%d\n", strlen(&p + 1));
//同上

printf("%d\n", strlen(&p[0] + 1));
//&p[0]得到的是字符a的地址,加1后得到的是字符b的地址,得到5

return 0;

}

int main()
{
char arr[] = “abcdef”;
printf(“%d\n”, sizeof(arr));
//此时数组名arr是整个数组的地址,其大小为7*1=7

printf("%d\n", sizeof(arr + 0));
//此时数组名是首元素的地址,是char*类型的数据,其大小为4/8个字节

printf("%d\n", sizeof(*arr));
//此时数组名为首元素的地址,解引用后是a,char类型,其大小为1个字节

printf("%d\n", sizeof(arr[1]));
//arr[1]为字符b,为char类型,其大小为1个字节

printf("%d\n", sizeof(&arr));
//此时的数组名是整个数组的地址,是数组指针,是地址,其大小为4/8

printf("%d\n", sizeof(&arr + 1));
//此时的数组名是整个数组的地址,,是数组指针,加1后还是数组值,是地址,其大小为4/8个字节

printf("%d\n", sizeof(&arr[0] + 1));
//&arr[0]是字符a的地址,是char*类型的指针,+1后还是指针,是地址,其大小为4/8个字节


printf("%d\n", strlen(arr));
//此时数组名是首元素的地址,得到6

printf("%d\n", strlen(arr + 0));
//同上

printf("%d\n", strlen(*arr));
//*arr指的是字符a,非法访问--error

printf("%d\n", strlen(arr[1]));
//同上

printf("%d\n", strlen(&arr));
//此时的数组名是整个数组的地址,是首元素的地址,可得到6

printf("%d\n", strlen(&arr + 1));
//此时数组名是整个数组的地址,+1跳过整个数组,不知道结束符在哪里,得到的值是随机的

printf("%d\n", strlen(&arr[0] + 1));
//&arr[0]+1是字符b的地址,得到5

return 0;

}

例题3 :二维数组

int main()
{
//二维数组
int a[3][4] = { 0 };

printf("%d\n", sizeof(a));
//此时的数组名是整个数组,其大小为3*4*4=48

printf("%d\n", sizeof(a[0][0]));
//是整数0,是int类型,其大小为4个字节

printf("%d\n", sizeof(a[0]));
//此时a[0]首行的数组名,是整行的数组,大小为4*4=16

printf("%d\n", sizeof(a[0] + 1));
//此时a[0]是首行数组首元素的地址,+1后还是int*类型的指针,是地址,其大小为4/8

printf("%d\n", sizeof(*(a[0] + 1)));
//由上知道,解引用后是int类型的整数,其大小为4

printf("%d\n", sizeof(a + 1));
//此时数组名a是首元素的地址,首元素是int [4]类型的数组,
//加1后是第二行的数组地址,是地址其大小就是4/8

printf("%d\n", sizeof(*(a + 1)));
//由上知,a+1是第二行的地址,解引用后int [4]类型的数组,其大小为4*4=16

printf("%d\n", sizeof(&a[0] + 1));
//此时a[0]是第一行数组名,&a[0]取得是第一行数组的地址,+1后是第二行数组的地址,是地址其大小就是4/8

printf("%d\n", sizeof(*(&a[0] + 1)));
//由上知&a[0] + 1是第二行的地址,解引用后是int [4]类型的数组,其大小为4*4=16

printf("%d\n", sizeof(*a));
//*a得到首元素a[0],是第一行数组的数组名,此时是第一行数组的整个数组,其大小为4*4=16

printf("%d\n", sizeof(a[3]));
//如果数组存在第四行,a[3]就是第四行的数组名,
//数组名单独放在sizeof内部,计算的是第四行的大小4*4=16

return 0;

}

总结

数组名在两种情况下是指整个数组:
(1)sizeof(数组名)(2)&数组名
其它的情况下,都是代表数组的首元素地址。

2.指针笔试题

题目 1:

int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int *ptr = (int *)(&a + 1);
printf( “%d,%d”, *(a + 1), *(ptr - 1));
return 0;
}
//程序的结果是什么?

在这里插入图片描述

题目 2:

//结构体的大小是20个字节
struct Test
{
int Num;
char *pcName;
short sDate;
char cha[2];
short sBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
int main()
{
printf(“%p\n”, p + 0x1);
printf(“%p\n”, (unsigned long)p + 0x1);
printf(“%p\n”, (unsigned int *)p + 0x1);
return 0;
}
在这里插入图片描述

题目 3:

int main()
{
int a[4] = { 1, 2, 3, 4 };
int *ptr1 = (int *)(&a + 1);
int *ptr2 = (int *)((int)a + 1);
printf( “%x,%x”, ptr1[-1], *ptr2);
return 0;
}
在这里插入图片描述

题目 4:

#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;
}
在这里插入图片描述
注意逗号表达式

题目 5:

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

题目 6:

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;
}

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);
在这里插入图片描述
关键是画出图

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杰深入学习计算机

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值