指针与数组笔试题解析


数组名的意义:

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

1.一维数组

1.1 整型数组

int main()
{
	int a[] = {1,2,3,4};
	printf("%d\n",sizeof(a));//16,sizeof单独加上数组名计算的是整个数组的大小
	printf("%d\n",sizeof(a+0));//4或者8,这里数组名不是单独在sizeof内,所以会变成数组首元素的地址,而指针的大小根据选择的是32位还是64位而不同。
	printf("%d\n",sizeof(*a));//4,a是首元素的地址,被解引用后就是首元素。整型为4个字节大小
	printf("%d\n",sizeof(a+1));// 4/8,表示数组第二个元素的地址
	printf("%d\n",sizeof(a[1]));//4,表示数组第一个元素是整型
	printf("%d\n",sizeof(&a));// 4/8,&数组名拿到是整个数组的地址,而整个数组的地址也是指针,所以大小还是4或者8
	printf("%d\n",sizeof(*&a));//16,取地址和解引用相互抵消,使得本质上是sizeof(a)
	printf("%d\n",sizeof(&a[0]));//4/8,计算的数组首元素的地址,也就是指针
	printf("%d\n",sizeof(&a[0]+1));//4/8,计算的是数组第二个元素的地址,也就是指针
	return 0;
}
//打印结果
/*
16
8
4
8
4
8
16
8
8
*/

1.2 字符数组

#include <stdio.h>
int main()
{
	char arr[] = {'a','b','c','d','e','f'};
	printf("%d\n",sizeof(arr));
	printf("%d\n",sizeof(arr+1));
	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;
	//与上面解释类似
}
//打印结果:
/*
6
8
8
1
1
8
8
8
*/
#include <stdio.h>
#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));//随机值,表示的是从数组的首元素开始计算直到碰到'\0'为止的长度
	printf("%d\n",strlen(*arr));//错误写法,strlen函数参数要传地址
	printf("%d\n",strlen(arr[1]));//错误写法,strlen函数参数要传地址
	printf("%d\n",strlen(&arr));/*随机值,虽然&arr表示的是整个数组的地址,但是整个数组的地
	址依旧是用数组首元素的地址代表。表示的是从数组的首元素开始计算直到碰到'\0'为止的长度*/
	printf("%d\n",strlen(&arr+1));//随机值,表示的是从数组的最后一个元素后的地址开始计算直到碰到'\0'为止的长度。会比第一个随机值数少6个字节
	printf("%d\n",strlen(&arr[0]+1));//随机值,表示从数组第二个元素地址开始计算直到碰到'\0'为止的长度。会比第一个随机值数少1个字节
	
	return 0;
}
//打印结果:
/*(注释掉错误写法后)
42
42
42
36
41
*/
#include <stdio.h>
int main()
{
	char arr[] = "abcdef";
	printf("%d\n",sizeof(arr));
	printf("%d\n",sizeof(arr+1));
	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));
	//整体解释和第一道题类型,不过要注意的是sizeof会计算隐藏的'\0'的大小。
	return 0;
}
//打印结果:
/*
7
8
8
1
1
8
8
8
*/
#include <stdio.h>
#include <string.h>
int main()
{
	char arr[] = "abcdef";
	printf("%d\n",strlen(arr));//6,该数组arr最后隐藏了一个'\0',strlen计算到'\0'为止
	printf("%d\n",strlen(arr+0));//6,该数组arr最后隐藏了一个'\0',strlen计算到'\0'为止
	printf("%d\n",strlen(*arr));//错误写法,strlen函数参数要传地址
	printf("%d\n",strlen(arr[1]));//错误写法,strlen函数参数要传地址
	printf("%d\n",strlen(&arr));//6,&arr虽然表示整个数组的地址,但是地址是用数组首元素地址来代表的。
	printf("%d\n",strlen(&arr+1));//随机值,&arr表示整个数组的地址,+1跳过整个数组,也跳过了'\0',直到找到后面的'\0'才会停止
	printf("%d\n",strlen(&arr[0]+1));//5,表示从数组的第二的元素地址开始往后计算长度。	
	return 0;
}
//打印结果
/*(注释掉错误写法后)
6
6
6
26
5
*/
#include <stdio.h>
int main()
{
	char* arr = "abcdef";
	printf("%d\n",sizeof(arr));//4/8,这里的arr不能等同于数组,arr就是指针,这个指针指向了"abcdef"这个常量字符串
	printf("%d\n",sizeof(arr+1));//4/8,arr+1就表示该常量字符串第二个元素的地址
	printf("%d\n",sizeof(*arr));//1,对指针解引用得到的就是首元素'a',类型char大小为1字节。
	printf("%d\n",sizeof(arr[0]));//1,arr[0]数组首元素'a'
	printf("%d\n",sizeof(&arr));//4/8,&arr表示arr的地址也就是一个二级指针
	printf("%d\n",sizeof(&arr+1));//4/8,&arr+1也是二级指针,
	printf("%d\n",sizeof(&arr[0]+1));//4/8,表示第二个元素'b'的地址
	return 0;
}
//打印结果:
/*
8
8
1
1
8
8
8
*/
#include <stdio.h>
#include <string.h>
int main()
{
	char* arr = "abcdef";
	printf("%d\n",strlen(arr));//6,arr存放的就是首元素的地址
	printf("%d\n",strlen(arr+1));//5,传入第二个元素的地址
	printf("%d\n",strlen(*arr));//错误写法,strlne必须传地址进去
	printf("%d\n",strlen(arr[0]));//错误写法,strlne必须传地址进去
	printf("%d\n",strlen(&arr));//随机值,&arr是首元素'a'地址的地址,是一个二级指针,会一直找到下一个'\0'为止。
	printf("%d\n",strlen(&arr+1));//随机值,是一个二级指针(不一定在&arr后面),会一直找到下一个'\0'为止。
	printf("%d\n",strlen(&arr[0]+1));//5,传入第二个元素的地址
	return 0;
}
//打印结果:
/*(注释掉错误写法后)
6
5
3
11
5
*/

2. 二维数组

#include <stdio.h>
int main()
{
	int a[3][4] = {0};
	printf("%d\n",sizeof(a));//48,sizeof(数组名)计算的整个数组的大小
	printf("%d\n",sizeof(a[0][0]));//4,a[0][0]就是首元素
	printf("%d\n",sizeof(a[0]));//16,a[0]是第一行这个一维数组的数组名
	//数组名算是单独放在sizeof内部了,计算的是整个数组的大小,大小是16个字节
	printf("%d\n",sizeof(a[0]+1));//4/8,a[0]是第一行数组名,+1就不算单独放到sizeof中了。
	printf("%d\n",sizeof(*(a[0]+1)));//4,相当于a[0][1],拿到了数组第1行第2列的元素
	printf("%d\n",sizeof(a+1));// 4/8,数组名除俩个的特殊情况外都是数组首元素的地址,
	//这里加1拿到就是第二行的地址,是指针
	printf("%d\n",sizeof(*(a+1)));//16,相当于a[1],计算的第二行的大小
	printf("%d\n",sizeof(&a[0]+1));//4/8,&a[0]+1,a[0]相当于第一行的数组名,&a[0]就是第一行数组的地址,加1跳过第一行,就是第二行数组的地址,是指针。
	printf("%d\n",sizeof(*(&a[0]+1)));//16,计算的是第二行的大小,&a[0]拿到第一行的地址,然后+1拿到第2行的地址,再解引用拿到就是第二行了。
	printf("%d\n",sizeof(*a));//16,a表示的一行的地址,*a就是拿到第一行,
	printf("%d\n",sizeof(a[3]));//16,虽然数组越界了但是,在sizeof的执行过程中是不会使用a[3]的,sizof(a[3])会把a[3]理解为第4行的数组名,
	return 0;
}
//打印结果:
/*
48
4
16
8
4
8
16
8
16
16
16
*/

3.指针笔试题

3.1 练习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;
}
//打印结果:2,5
/*
解释:&a拿到的是整个数组的地址,加1后跳过整个数组来到数组最后一个元素后面。也就说明了ptr的指向的地址再5的地址的后面,然后强制类型转换成整型指针,而整型指针-1只会前移动4个字节,ptr会指向5的地址。而a是数组名,表示数组首元素的地址,+1后就来到了第二个元素的地址。
*/

指针的指向

3.2 练习2

#include <stdio.h>
//这个结构体的大小是20个字节
struct test
{
	int Num;
	char* pcname;
	short sdata;
	char cha[2];
	short sba[4];
}*p = (struct Test*)0x100000;
//假设p的值为0x100000.
//已知test结构体的大小是20个字节
int main()
{
	printf("%p\n",p+0x1);
	printf("%p\n",(unsigned long)p+0x1);
	printf("%p\n",(unsigned long*)p+0x1);
	return 0;
}
//打印结果:
/*
00100014
00100001
00100004
*/
/*
解释:这里p指向的地址是0x100000。0x1就是1的16进制表达。p加1,因为p指向类型是struct test,类型大小20个字节,加1后也会跳过20这个字节(转换成16进制就是14).
后面p指针被强制类型转换成了一个无符号长整形的变量,这个类型不是指针变量,加1就是整数加1.
最后一个强制类型转换成了一个无符号长整形指针变量,是指针,然后无符号长整形的大小是4个字节,加1也就是跳过4个字节。
*/

3.3 练习3

#include <stdio.h>
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);//%x为16进制打印
	return 0;
}
//打印结果:4,2000000
/*
解释放下面
*/

ptr1:&a+1表示的跳过这个数组后的地址,也就是4后面的地址,然后被强制类型转换为了int*
ptr2:a是数组首元素的地址,都是被强制类型转换为了整型,然后+1,因为是整型加1就是数字加1.然后又被强制类型转换成了int*。
此时的指向如图所示
指针的指向
因为元素在系统当中是小端存储的,
1会被存储为:01 00 00 00
此时ptr2指向的就是01后面00的位置。
我们又知道数组中1的后面是2。
小端存储就是 01 00 00 00 02 00 00 00
ptr2被强制类型转换为了int*,解引用会一次取出4个字节,取出的就是00 00 00 02,将顺序反转成正常顺序就是02000000,打印时省略掉了第一个0变成了200000
ptr1[-1]的意思就是*(prt1-1).就拿出来4.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Yui_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值