c语言指针经典笔试题

 指针的笔试题目

//深度讨论数组名
int main1()
{
	int a[] = { 1,2,3,4 };
	printf("%d\n", sizeof(a));  //sizeof内部出现数组名代表是整个数组的大小 //16
	printf("%d\n", sizeof(a + 0));  //首元素地址+0还是首元素地址 4/8
	printf("%d\n", sizeof(*a));  //首元素地址进行解引用相当于a[0]是4个字节
	//*a中的a是数组首元素的地址,* a就是对首元素的地址解引用,找到的就是首元素
	//首元素的大小就是4个字节
	printf("%d\n", sizeof(a + 1));  //首元素地址+1 相当于a[1]的地址 是地址就是4/8
	printf("%d\n", sizeof(a[1]));  //第二个元素大小//4
	printf("%d\n", sizeof(&a));   //取地址数组名,取的是整个数组的地址,是地址就是4/8 
	printf("%d\n", sizeof(*&a));
	//&a----->的类型是int(*)[4] &a拿的是数组名的地址,数组指针解引用拿到了这个数组是
//是数组的大小就是16
	printf("%d\n", sizeof(&a + 1));
	//取数组名+1相当于跳了一个数组的大小,是地址就是4/8
	printf("%d\n", sizeof(&a[0]));
	//取第1个元素的地址 是地址就是4/8
	printf("%d\n", sizeof(&a[0] + 1));	       //取第2个元素的地址 是地址就是4/8
	return 0;
}


int main2()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%d\n", sizeof(arr));//sizeof内部出现数组名代表是整个数组的大小 //6
	printf("%d\n", sizeof(arr + 0));//首元素'a'的地址---4/8
	printf("%d\n", sizeof(*arr)); //'a'的大小/1
	printf("%d\n", sizeof(arr[1]));//'a'的大小/1
	printf("%d\n", sizeof(&arr));//取出整个数组的地址是地址就是4/8
	printf("%d\n", sizeof(&arr + 1));//跳过一个数组的地址,是地址就是4/8
	printf("%d\n", sizeof(&arr[0] + 1));//'b'的地址是地址就是4/8
	return 0;

}
#include <string.h>
int main3()
{
	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));//相当于strlen('a')strlen(地址)//err 是一个野指针
	printf("%d\n", strlen(arr[1]));//野指针
	printf("%d\n", strlen(&arr));//取数组的地址,数组的地址也是从‘a'的地址开始的   随机值
	printf("%d\n", strlen(&arr + 1));//取数组名+1跳过了一个数组的地址,   随机值-6
	printf("%d\n", strlen(&arr[0] + 1));  // 首元素的地址+1相当于  是字符b的地址开始  随机值-1

    return 0;
}

int main4()
{
	
	char arr[] = "abcdef";//[a b c d e f\0]
	printf("%d\n", sizeof(arr)); //计算的是整个数组的大小,7
	printf("%d\n", sizeof(arr + 0));//首元素地址 相当于是‘a'的地址 是地址就是4/8
	printf("%d\n", sizeof(*arr));//’a'元素的大小  1
	printf("%d\n", sizeof(arr[1]));//1
	printf("%d\n", sizeof(&arr));//取数组的地址 也是从‘a'的地址开始的 也是 4/8
	printf("%d\n", sizeof(&arr + 1));//跳了一个数组的地址是地址就是  4/8
	printf("%d\n", sizeof(&arr[0] + 1)); //相当于是’b'的地址  4/8
	return 0;
}
//strlen是求字符串长度的,关注的是字符串中的\0,计算的是\0之前出现的字符的个数
//	//strlen是库函数,只针对字符串
//	//sizeof只关注占用内存空间的大小,不在乎内存中放的是什么
//	//sizeof是操作符
int main5()
{
	char arr[] = "abcdef";//[a b c d e f\0]
	printf("%d\n", strlen(arr));//6
	printf("%d\n", strlen(arr + 0));//6
	//printf("%d\n", strlen(*arr));//err
	//printf("%d\n", strlen(arr[1]));//err
	printf("%d\n", strlen(&arr));//‘a’字符的地址开始  6
	printf("%d\n", strlen(&arr + 1)); //跳过了\0 从\0后面开始  随机值
	printf("%d\n", strlen(&arr[0] + 1));  //从'b'字符开始走  5
	
	return 0;
}
int main()
{
	char* p = "abcdef";//[a b c d e f\0]
	printf("%d\n", sizeof(p));//p指向的是字符a的地址  4/8
	printf("%d\n", sizeof(p + 1)); //指向的是字符b的地址 4/8
	//printf("%d\n", sizeof(*p));  //err
	//printf("%d\n", sizeof(p[0])); //err
	printf("%d\n", sizeof(&p));//取出的是一级指针的地址  4/8
	printf("%d\n", sizeof(&p + 1)); //4/8
	printf("%d\n", sizeof(&p[0] + 1)); //4/8

	printf("%d\n", strlen(p)); //p指向的是a的地址  6
	printf("%d\n", strlen(p + 1)); //p指向的是b的地址 5
	//printf("%d\n", strlen(*p)); //P找到了a的这个字符 err
	///printf("%d\n", strlen(p[0])); //err
	printf("%d\n", strlen(&p)); //取出的是一级指针的地址 随机
	printf("%d\n", strlen(&p + 1));//随机
	printf("%d\n", strlen(&p[0] + 1));//5  //P+1  p指向的是b的地址 
	
	return 0;
}

2a6da45685024ceba483a6941e67b500.png

为什么strlen(&P)是随机值是因为指向p的那块空间上的地址存储方式不确定,有可能是大端存储,也可能是小段存储

2c1f4eef565b44e9b2afb66b40d5ac9d.png

int main()
{
	int a[3][4] = { 0 };
	printf("%d\n", sizeof(a));//48
	printf("%d\n", sizeof(a[0][0]));//4
	printf("%d\n", sizeof(a[0]));a[0]是第一行这个一维数组的数组名,单独放在sizeof内部,a[0]表示第一个整个这个一维数组
	//sizeof(a[0])计算的就是第一行的大小 也就是第一行的数组名  16
	printf("%d\n", sizeof(a[0] + 1)); //没有单独放在sizeof内部,表示的是首元素地址 
	//也就是第一行这个一维数组的第一个元素的地址--a[0][0]的地址 然后+1 就是第一行第二个元素的地址  4/8
	printf("%d\n", sizeof(*(a[0] + 1)));  //第一行第二个元素的地址进行解引用 也就是arr[0][1]元素的大小  --4
	printf("%d\n", sizeof(a + 1));//  第一行的地址+1 相当于跳到了第二行的地址 是地址就是4/8
	printf("%d\n", sizeof(*(a + 1)));  //第二行的地址解引用 ---就相当于是第二行的数组名  16
	printf("%d\n", sizeof(&a[0] + 1));// 对第一行的数组名取地址 相当于是第一行的地址,第一行的地址+1相当于是第二行的地址	4/8
	printf("%d\n", sizeof(*(&a[0] + 1)));  //第二行的地址解引用相当于拿到了第二行的数组名 16
	printf("%d\n", sizeof(*a)); //第一行地址解引用 拿到了第一行的数组名 16
	printf("%d\n", sizeof(a[3]));//第三行的数组名  虽然越界了 但是不影响计算它内部的大小  16

	return 0;
}

1.题目1

890cbd3642604ef4add471ab86f89e52.png

7a151008d1594f9bbb63db023e37a881.png

取数组的地址说明这个指针是的类型是int(*)[5]的,说明这个指针是数组指针,指针指向这个数组,数组有5个元素,每个元素的类型是int类型

题目的指针是int*类型,说明我们要强制类型转换成int*类型的

2.题目2cb01e0fd326b47148880ebc2fae25355.png

这里的p是一个结构体指针

1.结构体指针+1相当于跳过的是一个结构体的大小 已经知道一个结构体的大小是20个字节就相当于跳了20个字节。0x100000+20----ox1000014

2.把p强制类型转换成无符号长整形,,已经知道1,048,576是p转换成无符号长整形的数据,它+1= 048,577

3.把p转换成无符号整形指针类型  +1就相当于跳过一个无符号整形 相当于+4 = 1,048,576+4

3.题目3

cdb17571d080450bb267fa2694fdfbea.png

ca604de2b62442a7be44a7a4e933590e.png

取数组的地址说明这个指针是的类型是int(*)[4]的,说明这个指针ptr1是数组指针,指针指向这个数组,数组有4个元素,每个元素的类型是int类型

题目的指针是int*类型,说明我们要强制类型转换成int*类型的

ptr1[-1]是指向的是04 00 00 这块区域的 同理也是00是高地址的 04是低地址的拿出来的时候就是低地址在后面  00 00 00 04  以16进制打印的时候前面的0全部删除掉 就是4了6643a617efc041d09a28d3da67a47389.png

ptr2: 首先这个a是数组名,数组名是首元素地址,首元素地址+1是跳过一个整形也就是4个字节,题目强制类型转换成了int类型说明现在的a不是地址了是一个整数,它+1就说明加了一个整数

1f7418f06fc44e22bb86467dbff49fa0.png

503bbf4c734248098dfb3519be101ec2.png

比如1的16进制是 00 00 00 01

在内存是小端存储模式,01是低地址处,----01 00 00 00

a+1强制类型转换成int*类型的指针,所以ptr2就指向了 00 00 00 02这块起始地址。因为 00 00 00 02在内存中是以小端模式存储,拿出来的时候就是02 00 00 00 以16进制打印的时候就是200 00 00

9a23030372ac468a9f9ff0520d565a1b.png 因为·02是高位的地址就应该放在低地址处

4.题目4

b702977c8535441fb412cc001a00144a.png

b40199ea037e4463aa6d80e0f224c818.png

首先这个二维数组的元素是以逗号表达式的形式展开,你要明确这个数组里的元素是{1,3,5,0,0,0}p指向了第一行的数组名,此时的数组名表示的一行的地址,数组名没有放在sizeof内部,也没有取地址,说明数组名表示首元素地址  也就是a[0][0]的地址然后解引用就是1了

5.题目5

b492434a36954de4b9c7e6264734d17f.png

d6c28228bf15467c9389365bb50e2bf4.png

这里的a作为数组名,它是第一行的地址,它的类型是int(*)[5] ,因为二维数组的数组名代表的是第一行的地址,也就是第一行数组名的地址  一维数组名的地址就需要用一维数组的指针来接受。

这里的p是一个数组指针,它指向的是一个数组,这个数组有4个元素,每个元素的类型是int类型

这里把二维数组的数组名赋给数组指针    类型存在差异,但不影响,只不过是报警告

再来看看   p是一个数组指针 它+1跳过一个数组的大小,这个数组有4个元素,每个元素的类型是int类型,相当于跳了4个整形的大小,p[4][2]可以看成 *( *(p+4)+2)

*(p+4)这个相当于p跳了4个整形的大小 再图可以看出 它跳到了a[3][1]的 地址,然后解引用找到了arr[3]的数组名,就可以访问相当于arr[3][1]~ arr[3][4]这块区域的元素的地址,然后+2跳过二个整形长度指向了arr[3][3]这块地址然后解引用找到了arr[3][3] 这个元素 

我们是把p[4][2]看成arr[3][3]  ,指针-指针的绝对值是元素之间的个数,他们相差了4个 又因为地址再内存中是从低到高存放的,所以结果是-4

打印地址是打印它在内存中的地址,所以这里不考虑大小端字节序,也不考虑原码补码反码,

 b5479e31a1884970a613d25db800e46c.png

再x86的环境下就是FF  FF FC 记住打印内存是打印反码的形式打印内存

6.题目6

9d4cd629a2964a28b016963a17875eb3.png

44db0f5a4ea4431fb01ff8124a1fd45a.png

7.题目7

6ba3870e47684f4aaee03c5564af11ec.png

3a2907939874406285bf32d711d18111.png

pa是指向的是a的起始地址

pa++跳到了第二行,对pa解引用找到了a的地址相当于指向了a的地址

56b40f83eeac464f9bae7f5885599165.png

pa指向了a,a是一个指针数组pa指向的对象是一个char*类型的,第二*说明pa是一个指针

pa++=pa+1  自然是跳过一个char*类型  也就是4个字节。

int*p 是一个指针,它指向的对象是int类型,所以+跳过了4个字节。

9ecc4ba01a964dd283eae59c6732bc5e.png

8.题目8

23e5c247349d4f1d965dde986dfed11f.png

3a298622125a4276a5144d1f3ec49896.png

7208ae86ba4b4620920724230840e7e5.png

11

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值