• 指针和数组笔试题的透析


    一、前言

    那么好了好了,宝子们,从今天开始开始总结暑假博客,从指针开始,后续,来吧开始整活!⛳️

    二、一维数组例题透析:

    关于数组名的理解:
    arr,首先数组名是数组首元素的地址 毋庸置疑
    &arr,取地址符号加上数组名取出的是整个数组的地址

    但是有2个例外:
    1.sizeof后面括号内只有数组名的话,计算的是整个数组的大小单位是字节。
    2.&加上数组名,取出的是整个数组的地址

    还有一点特别需要注意:

    只要是指针也就是地址,它的大小必然是4或8个字节,4/8个字节的原因是在不同的环境下x86和x64。

    1.int a[ ] = { 1,2,3,4 };

    #include 
    int main()
    {
    	int a[] = { 1,2,3,4 };
    	printf("%d\n", sizeof(a));//计算的是整个数组的大小:4*4=16
    	printf("%d\n", sizeof(a+0));//sizeof(a+0)得到的是数组首元素的地址:4/8
    	printf("%d\n", sizeof(*a));//a是数组首元素的地址,*(解引用后)便是数组首元素:1,大小为:4
    	printf("%d\n", sizeof(a+1));// Sizeof(a)是数组首元素地址,加1,也就是数组第2个元素的地址,只要是地址,它的大小就是4/8个字节
    	printf("%d\n", sizeof(a[1]));//数组的下标访问,不必多说,直接就是:4
    	printf("%d\n", sizeof(&a));//这里不要被表面现象所迷惑了,&a取出的是整个数组的地址,它本质上还是个地址,所以说只要是地址它的字节大小就是:4/8
    	printf("%d\n", sizeof(*&a));//*和&可以说是抵消了,所以说本质上还是sizeof(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,也就是取出的是数组中第2个元素的地址:4/8个字节
    
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    2.char arr[ ] = { ‘a’,‘b’,‘c’,‘d’,‘e’,‘f’};

    int main()
    {
    	char arr[] = { 'a','b','c','d','e','f'};
    	printf("%d\n", sizeof(arr));//因为sizeof内部的括号只有arr,arr代表整个数组的大小:1*6
    	printf("%d\n", sizeof(arr+0));//4/8
    	printf("%d\n", sizeof(*arr));//这里的arr是数组首元素地址,*后就是数组首元素大小为:1个字节
    	printf("%d\n", sizeof(arr[1]));//1
    	printf("%d\n", sizeof(&arr));//取出的是整个数组的地址,地址的大小只有4/8
    	printf("%d\n", sizeof(&arr+1));//4/8
    	printf("%d\n", sizeof(&arr[0]+1));//4/8
    
    
    	//声明:strlen接收的参数类型是(指针):const char * str
    	//strlen函数只有遇到‘\0’为结束标志
    
    	printf("%d\n", strlen(arr));//随机值因为上面这个数组里面没有'\0',所以strlen要不断的往下遍历,直到遇到'\0'为止。
    	printf("%d\n", strlen(arr + 0));//随机值
    	printf("%d\n", strlen(*arr)); // error,arr是数组首元素的地址, * arr就是数组首元素,就是'a' - 97
    	//strlen函数参数的部分需要传一个地址当我们传递的是"a"时,'a"的ASCII码值是97,那就是将97作为地址传参
    	//strLen就会从97这个地址开始统计字符串长度,这就非法访问内存了
    	printf("%d\n", strlen(arr[1]));//error
    	printf("%d\n", strlen(&arr));//随机值
    	printf("%d\n", strlen(&arr+1));//随机值
    	printf("%d\n", strlen(&arr[0]+1));//从第二个元素的地址开始访问,还是随机值
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    3.char arr[ ] = “abcdef”;

    char arr[] = "abcdef";
    	printf("%d\n", sizeof(arr));//因为还有'\0'所以=1*7=7
    	printf("%d\n", sizeof(arr + 0));//首元素的地址:4/8
    	printf("%d\n", sizeof(*arr));//对数组首元素地址*,也就是第1个元素a:1
    	printf("%d\n", sizeof(arr[1]));//1
    	printf("%d\n", sizeof(&arr));//整个数组的地址:4/8
    	printf("%d\n", sizeof(&arr + 1));//4/8
    	printf("%d\n", sizeof(&arr[0] + 1));//4/8
    
    
    	printf("%d\n", strlen(arr));//6
    	printf("%d\n", strlen(arr + 0));//6
    	printf("%d\n", strlen(*arr));//error
    	printf("%d\n", strlen(arr[1]));//error
    	printf("%d\n", strlen(&arr));//整个数组的地址:6
    	printf("%d\n", strlen(&arr + 1));//取出整个数组的地址加1,相当于指针这个数组指向最后一位的后面,随机值
    	printf("%d\n", strlen(&arr[0] + 1));//从b开始,:5个
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    4.char* p = “abcdef”;

    
    	char* p = "abcdef";
    	printf("%d\n", sizeof(p));//4/8  :p是一个指针变量
    	printf("%d\n", sizeof(p+1));//4/8  :p+1是'b'的地址,是地址大小就是4/8个字节 
    	printf("%d\n", sizeof(*p));//1   :就是a
    	printf("%d\n", sizeof(p[0]));//1    :就是a
    	printf("%d\n", sizeof(&p));//4/8   :取出的是整个字符串的地址:  char**
    	printf("%d\n", sizeof(&p + 1));//4/8   :char**
    	printf("%d\n", sizeof(&p[0] + 1));//4/8   :&p[0] + 1得到是'b'的地址
    
    
    
    	printf("%d\n", strlen(p));//6
    	printf("%d\n", strlen(p + 1));//   5      
    	printf("%d\n", strlen(*p));//error
    	printf("%d\n", strlen(p[0]));//error
    	printf("%d\n", strlen(&p));//随机值
    	printf("%d\n", strlen(&p + 1));//随机值
    	printf("%d\n", strlen(&p[0] + 1));//5
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    5.二维数组:int a[3][4] = { 0 };

    	//二维数组
    	int a[3][4] = { 0 };
    	printf("%d\n", sizeof(a));// a是数组名计算的,是整个数组的大小:3*4*4=48;
    	printf("%d\n", sizeof(a[0][0]));//第1行第1个元素的大小:4
    	printf("%d\n", sizeof(a[0]));//这里我们把a[0]看作一个一维数组的数组名:4*4=16
    	printf("%d\n", sizeof(a[0]+1));//a[0]作为第一行的数组名,没有单独放在sizeo内部,没有&
    	//a[0]表示数组首元素的地址,也就是a[0][0]的地址	所以a[0]+1是第一行第二个元素的地址,是地址就是4/8个字节
    	printf("%d\n", sizeof(*a[0]+1));//4  //计算的是就是第一行第2个元素的大小
    	printf("%d\n", sizeof(a+1));// a不是单独放在size of内部就代表数组首元素地址也就是第1行数组的地址,加1,也就是第2行数组的地址:4/8
    	printf("%d\n", sizeof(*(a+1)));//对第2行数组地址*  就是4*4=16
    	printf("%d\n", sizeof(&a[0] + 1));//因为a[0]是第一行数组的数组名,对第1行数组数组名取地址之后再加1,也就是第2行数组的地址:4/8
    	printf("%d\n", sizeof(*(&a[0] + 1)));//对第2行数组地址整个*,4*4=16
    	printf("%d\n", sizeof(*a));//如果a不是单独放在size of内部,那么a就代表数组首元素地址,也就是数组第1行的地址   *后=4*4=16
    	printf("%d\n", sizeof(a[3]));//a[3]代表第三行数组数组名:4*4=16
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    对二维数组的深度理解:
    在这里插入图片描述

    三、指针笔试题

    1.例一:

    
    int main()
    {
    	int a[5] = { 1,2,3,4,5 };
    	int* ptr = (int*)(&a + 1);
    	//取地址加数组名(& a),取出的是整个数组的地址,再+1指向5的后面!!!
    	printf("%d %d", *(a + 1), *(ptr - 1));
    	//a+1:就是数字数元素地址加1,然后*后就是2;
    	//刚开始ptr指的是5的后面,再减1就是指向了5
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述

    2.例二:

    这道题主要考察的是:指针类型:决定了指针+1到底加几?

    //由于还没学习结构体,这里告知结构体的大小是20个字节
    struct Test
    {
    	int Num;
    	char* pcName;
    	short sDate;
    	char cha[2];
    	short sBa[4];
    }* p = (struct Test*)0x100000;
    
    //假设p 的值为0x100000。 如下表表达式的值分别为多少?
    //已知,结构体Test类型的变量大小是20个字节
    int main()
    {
    	printf("%p\n", p + 0x1);//0x100000+1:因为p是一个结构体指针,结构体指针+1跳的是整个结构体,也就是加了20个字节
    	//0x100000+20?错!因为0x100000是16进制的:0x100014
    	printf("%p\n", (unsigned long)p + 0x1);
    	//在这里我们把结构体指针强制类型转化为无符号的数字:+1=0x100001
    	printf("%p\n", (unsigned int*)p + 0x1);
    	//这里我们把结构体指针,p强制类型转化为int*,+1就跳过4个字节:0x100004
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    在这里插入图片描述
    注意前提:环境为X86:
    在这里插入图片描述

    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);
    	//ptr1:=4;
    	// a是数组首元素地址,把a数组首元素地址强制转换为int整型,强制转化为int整型之后再+1就是单纯的加数字1了,之后再将这个数字强制转化为int*。
    	//打印的是地址:
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述

    在这里插入图片描述

    4.例四:

    考察:逗号表达式!

    int main()
    {
    	int a[3][2] = { (0, 1), (2, 3), (4, 5) };//不要被表面现象所迷惑了,如果012345要存到二维数字中,它每个数组都要用大括号括起来,
    	//而它是用小括号,所以说它是一个逗号表达式,所以说实际上存进去的只有1 3 5这三个数字后面其他的都是0
    	int* p;
    	p = a[0];//a[0]之前不是讲过了吗?是第1行数组的数组名:也就是第1行数组首元素的地址。
    	printf("%d", p[0]);//1
    	
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述

    在这里插入图片描述

    5.例五:

    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));
    	//1.ptr1:取地址&+数组名aa是取出了整个数组的地址,再加一就是跳过整个二维数组。-1指向了10
    	//2.ptr2:aa是数组首元素地址,在二维数组中,我们把每一行看作一个元素,+1的话就是跳过了第1行,指向了第2行首元素的地址,-1指向了5
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述

    **++cpp步骤一:
    在这里插入图片描述

    在这里插入图片描述
    好了,今天的分享就到这里了

    如果对你有帮助,记得点赞👍+关注哦!
    我的主页还有其他文章,欢迎学习指点。关注我,让我们一起学习,一起成长吧!

    在这里插入图片描述

  • 相关阅读:
    智慧校园建设,需要哪些必要条件?
    Python Day9 字符串进阶【零基础】
    使用VBA创建数字金字塔
    019-第三代软件开发-Git提交规范
    [C++]多态(下)
    VSCode插件开发之contributes和命令
    数据仓库入门介绍
    Spring之AOP
    力扣46:全排列(Java回溯)
    transformers 之 head介绍
  • 原文地址:https://blog.csdn.net/weixin_75128035/article/details/133202738