IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> C语言进阶 - 指针4 -知识点整理 -- 指针和数组笔试题解析 -> 正文阅读

[数据结构与算法]C语言进阶 - 指针4 -知识点整理 -- 指针和数组笔试题解析

目录

?一、字符数组

二、二维数组

三、指针笔试题


?一、字符数组

int main()
{
	//类型一:
	char arr[] = { 'a','b','c','d','e','f' };//6
	//{a,b,c,d,e,f}
	printf("%d\n", sizeof(arr));//6,整个数组的大小
	printf("%d\n", sizeof(arr + 0));//4/8,首元素地址,地址4/8B
	printf("%d\n", sizeof(*arr));//1,首元素
	printf("%d\n", sizeof(arr[1]));//1,访问第二个元素
	printf("%d\n", sizeof(&arr));
    //4/8,整个数组的地址,地址4/8B,数组的地址用数组指针接收,类型应为char(*)[6]
	printf("%d\n", sizeof(&arr + 1));//4/8B,下一个数组的地址
	printf("%d\n", sizeof(&arr[0] + 1));//4/8B,第二个元素的地址
	
	printf("%d\n", strlen(arr));//随机值,19
	printf("%d\n", strlen(arr + 0));//随机值,19
	/*printf("%d\n", strlen(*arr));*///*arr - 'a' - 97 --- err
	//strlen 就以为传进来的'a'的ascll码值97就是地址,然后一直往后找'\0',导致野指针
	/*printf("%d\n", strlen(arr[1]));*///'b' -- 98 - err 
	printf("%d\n", strlen(&arr));//随机值,19
	//&arr传过去的类型位char (*)[6],而strlen接收的是char* ,类型不匹配,
	//但是strlen会认为你传过去的就是首元素a的地址,所以会和第一个一样往后找'\0',所以是随机值
	printf("%d\n", strlen(&arr + 1));
    //随机值  但和第一个随机值相差6,因为跳过了一个数组,6个字符,13
	printf("%d\n", strlen(&arr[0] + 1));
    //随机值,但和第一个随机值相比少1,因为是从第二个字符开始数,18

 
    //类型二:
	char arr[] = "abcdef";//7
	//{a,b,c,d,e,f,\0}
	printf("%d\n", sizeof(arr));//7
	printf("%d\n", sizeof(arr + 0));//4/8,首元素地址,地址-4/8B
	printf("%d\n", sizeof(*arr));//1,首元素地址,*arr就是首元素
	printf("%d\n", sizeof(arr[1]));//1,arr[1]就是第二个元素
	printf("%d\n", sizeof(&arr));//4/8,&arr是数组的地址,数组的地址也是地址,就是4/8B
	printf("%d\n", sizeof(&arr + 1));//4/8,,&arr是数组的地址,&arr+1是跳过整个数组后的地址
	printf("%d\n", sizeof(&arr[0] + 1));//4/8,&arr[0]+1是第二个元素的地址


	printf("%d\n", strlen(arr));//6
	printf("%d\n", strlen(arr + 0));//6
	printf("%d\n", strlen(*arr));//*arr,'a' -- 97 --err
	printf("%d\n", strlen(arr[1]));//'b'-- 98  -- err
	printf("%d\n", strlen(&arr));//6
	printf("%d\n", strlen(&arr + 1));//随机值,12
	
    //类型三:
    const char* p = "abcdef";
	printf("%d\n", sizeof(p));//p是一个指针变量 , 4/8B
	printf("%d\n", sizeof(p + 1));//P+1是字符b的地址 4/8
	printf("%d\n", sizeof(*p));//首元素的大小,1B
	printf("%d\n", sizeof(p[0]));//首元素的大小,1B
	printf("%d\n", sizeof(&p));//指针p的地址,4/8B
	printf("%d\n", sizeof(&p + 1));//p是一个char*类型,&p+1跳过一个char*,是一个地址,4/8B
	printf("%d\n", sizeof(&p[0] + 1));//第二个元素的地址,4/8B


	printf("%d\n", strlen(p));//6
	printf("%d\n", strlen(p + 1));//5
	printf("%d\n", strlen(*p));//err
	printf("%d\n", strlen(p[0]));//err
	printf("%d\n", strlen(&p));//随机值,3
	printf("%d\n", strlen(&p + 1));//随机值,与&p无关,指针p的大小是4/8个字节,+1,跳过4/8,
	//但是不知道指针p向后什么时候遇到\0,所以&p+1也是随机值,11
	printf("%d\n", strlen(&p[0] + 1));//5
	return 0;
}

二、二维数组


	//二维数组
	int a[3][4] = { 0 };
	printf("%d\n", sizeof(a));//48,整个数组的大小
	
	printf("%d\n", sizeof(a[0][0]));//4,0行0列的数
	
	printf("%d\n", sizeof(a[0]));
    //16,把每行看作一个一维数组,a[0]表示第一行的数组名,数组名单独放在sizeof内部
	
	printf("%d\n", sizeof(a[0] + 1));
    //4/8,a[0]没有单独放在sizeof内部,也没有取地址,所以表示的是第一行这个数组首元素的地址,
	//+1,表示第一行第二个元素的地址
	
	printf("%d\n", sizeof(*(a[0] + 1)));//4,第一行第二个元素
	
	printf("%d\n", sizeof(a + 1));
    //4/8,二维数组的数组名表示,没有单独放在sizeof内部,也没有&,所以表示首元素地址
	//而二维数组首元素的地址表示的是第一行的地址,+1表示第二行的地址,类型应为int(*)[4]
	//a + 1 -> &a[1],第二行的数组名&,那么就是第二行整个数组的地址
	
	printf("%d\n", sizeof(*(a + 1)));
    //16,*(a + 1),拿到的就是整个第二行数组
	//*(a+1) -> a[1],a[1]表示的是第二行数组
	
	printf("%d\n", sizeof(&a[0] + 1));//4/8
	//a[0]表示的是第一行的数组名,&a[0]表示的是第一行的地址,+1,表示的是第二行的地址 ,                     类型为int(*)[4]
	
	printf("%d\n", sizeof(*(&a[0] + 1)));//16
	//&a[0] + 1,第二行的地址,解引用拿到的是整个第二行
	//*(&a[0] + 1) -> *(&a[1]) -> a[1]
	
	printf("%d\n", sizeof(*a));//16
	//a没有单独放在sizeof内部,所以表示的是第一行的地址,第一行的地址解引用表示的是整个第一行 --  相当于第一行的数组名a[0]
	
	printf("%d\n", sizeof(a[3]));
    //16,只是看了一下第4行的类型,并没有真正访问第4行的内容,所以不算越界
	//或者说a[3]假设存在,就是第四行的数组名,sizeof(a[3]),就相当于把第四行的数组名单独放在sizeof内部
	//sizeof在计算的时候只看操作数的类型,不会访问对应空间

	//*(*(a + 0) + 1)  -- *(a + 0) 相当于a[0],a[0](第一行的数组名)并没有放在sizeof内部,所以表示的是第一行第一个元素的地址,
	//+1表示的是第一行第二个元素的地址,解引用表示的是第一行第二个元素---a[0][1]

?图解:

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

三、指针笔试题

//题目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;     
}

//*(a + 1), --> a 是首元素地址,+1表示第二个元素地址,解引用表示第二个元素  -->  2
//*(ptr - 1), --> (int *)(&a + 1)  --> &a表示整个数组的地址,+1表示跳过一个数组的大小
//-->强制类型转换为(int*) == ptr --> int *ptr表示ptr是一个指针,指向的是int类型的元素,    
ptr - 1,就是向前访问四个字节,也就是访问元素5的地址,解引用表示元素5

图解:

//题目2:
struct Test
{
 int Num;
 char *pcName;
 short sDate;
 char cha[2];
 short sBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
int main()
{
//struct Test* 
 p = (struct Test*)0x100000;
 printf("%p\n", p + 0x1);
//p 是struct Test*类型,每次访问20B,所以地址打印16进制为00100014
 
printf("%p\n", (unsigned long)p + 0x1);
//p 被强制转换为unsigned long类型,也就是100000+1,所以16进制打印为00100001,不管是2进制还是8进制,还是16进制,都只是他的表现形式
 
printf("%p\n", (unsigned int*)p + 0x1);
//p 是unsigned int*类型,跳过一个整形指针,每次访问4个字节,所以16进制打印为00100004
//指针才是访问4/8字节
 return 0; 
}
//题目3:
int main()
{
 ? ?int a[4] = { 1, 2, 3, 4 };
 ? ?int *ptr1 = (int *)(&a + 1);
    //&a是整个数组的地址,所以他的类型是int(*)[4],所以强制转换为(int*)
 ? ?int *ptr2 = (int *)((int)a + 1);
 ? ?printf( "%x,%x", ptr1[-1], *ptr2); //4 , 2000000
 ? ?return 0; 
}

图解:

//题目4:
#include <stdio.h>
int main()
{
	int a[3][2] = { (0, 1), (2, 3), (4, 5) };
    //这里是逗号表达式,不是{},所以只有三个元素{1,3,5}
	
    int* p;
	p = a[0];
	printf("%d", p[0]);//1
	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]);
    //FFFFFFFC,-4
 ? ?return 0; 
}

图解:

//题目6:
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));
    //10,5
 ? ?return 0; 
}

图解:

//题目7:
#include <stdio.h>
int main()
{
	char* a[] = { "work","at","alibaba" };
    //a,是一个数组,数组里面每个元素都是一个指针,每个指针指向一个字符串,
    //数组里面存放的是字符串的首元素的地址
	char** pa = a;
	pa++;
	printf("%s\n", *pa);//at
	return 0;
}

图解:

//题目8:
int main()
{
 char *c[] = {"ENTER","NEW","POINT","FIRST"};
 char**cp[] = {c+3,c+2,c+1,c};
 char***cpp = cp;
 printf("%s\n", **++cpp);//POINT
 printf("%s\n", *--*++cpp+3);//ER
 printf("%s\n", *cpp[-2]+3);//ST
 printf("%s\n", cpp[-1][-1]+1);EW
 return 0; 
}

图解:

知识点:??? arr[i][j]? <==>? *(*(arr+i)? + j)

?以上为指针和数组的笔试题内容,如有错误,烦请在评论区多多评论,互相学习😄

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-02-24 15:33:08  更:2022-02-24 15:33:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 15:35:44-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码