指针和数组笔试题解析【上】

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 指针和数组笔试题解析【上】
1.对数组名的理解


①数组名是数组首元素的地址


②但是有两个例外:


sizeof(数组名)这里的数组名表示整个数组,计算的是整个数组的大小,单位是字节。

&数组名,这里的数组名也表示整个数组,取出的是数组的地址。

//一维数组
int a[] = {1,2,3,4};//4个元素,每个元素是int类型(4个字节)
printf("%d\n",sizeof(a));
//16 数组名a单独放在sizeof内部,计算的是整个数组的大小,单位是字节,是16个字节
printf("%d\n",sizeof(a+0));
//a并非单独放在sizeof内部,也没有&,所以数组名表示首元素的地址,a+0还是首元素地址,是地址就是4/8个字节
printf("%d\n",sizeof(*a));
//a并非单独放在sizeof内部,也没有&,所以还是表示首元素地址,对a解引用,就是a[0],大小是4个字节
printf("%d\n",sizeof(a+1));
//a并非单独放在sizeof内部,也没有&,表示首元素地址,a+1就表示第二个元素的地址,等价于&a[1],是地址就是4/8个字节
printf("%d\n",sizeof(a[1]));
//a并非单独放在sizeof内部,也没有&,表示数组第二个元素,计算的是第二个元素的大小单位是字节-4
printf("%d\n",sizeof(&a));
//&a--表示的是:取出整个数组的地址,但是数组的地址也是地址,是地址就是4/8个字节
//数组的地址 和 数组首元素的地址的 本质区别是类型的区别,并非大小的区别
//a--int*             int* p= a;       解引用访问一个整型的大小
//&a--int *()[4]      int (*p)[4] =&a; 解引用访问一个数组的大小
printf("%d\n",sizeof(*&a));
//16字节--&a,取出数组的地址,解引用可以访问整个数组的大小,即4个整型的大小,就是16字节
//*和&可以互相抵消,所以sizeof(*&a)==sizeof(a),所以是16字节
printf("%d\n",sizeof(&a+1));
//4/8字节--&a取出的是数组a的地址,&a+1还是地址,是地址就是4/8个字节,需要理解的是,&a+1跳过的是一个数组
printf("%d\n",sizeof(&a[0]));
//4/8字节--取出的是数组首元素的地址,计算的是地址的大小,是地址就是4/8个字节
printf("%d\n",sizeof(&a[0]+1));
//4/8字节--&a[0]取出首元素的地址,+1就是第二个元素的地址,是地址就是4/8个字节

image.png

//字符数组
char arr[] = {'a','b','c','d','e','f'};
printf("%d\n", sizeof(arr));
//数组名arr单独放在sizeof内部,计算的是整个数组的大小,单位是字节,是6个字节
printf("%d\n", sizeof(arr+0));
//arr并非单独放在sizeof内部,也没有&,所以arr是首元素的地址,&arr[0],是地址就是4/8个字节
//在这里简单说明一下,指针变量的大小和类型无关,不管什么类型的指针变量,大小都是4/8个字节
//指针变量是用来存放地址的,地址存放需要多大空间,指针变量的大小就是几个字节
//32位环境下,地址是32个二进制位,需要4个字节
//64位环境下,地址是64个二进制位,需要8个字节
printf("%d\n", sizeof(*arr));
//arr表示数组首元素的地址,解引用就是数组首元素的,大小是1个字节
printf("%d\n", sizeof(arr[1]));
//arr[1]表示第二个元素,大小是1个字节
printf("%d\n", sizeof(&arr));
//&arr取出的是数组的地址,数组的地址也是地址,大小是4/8个字节
printf("%d\n", sizeof(&arr+1));
//&arr+1是跳过数组后的地址,也是地址,当然也是4/8个字节
printf("%d\n", sizeof(&arr[0]+1));
//&arr[0]取出首元素地址,+1就是第二个元素的地址,是地址就是4/8个字节

image.png


分析了上面的代码后,对上面的代码稍加修改,再来看一下输出的结果。


//strlen 求字符串长度,统计的是在字符串中\0之前的字符个数
char arr[] = {'a','b','c','d','e','f'};
//当前数组并没有在末尾有'\0'
printf("%d\n", strlen(arr));
//>=6随机值--arr是首元素的地址(没有'\0')
printf("%d\n", strlen(arr+0));
//arr是首元素地址,+0还是首元素地址,还是随机值
//printf("%d\n", strlen(*arr));
//通常给strlen传的参数是地址,arr是首元素的地址,*arr就是首元素,字符'a'的ASCII码值是97,
//站在strlen角度,认为传参进去的'a'-97就是地址,97作为地址直接进行访问,就是非法访问(错误代码)
//printf("%d\n", strlen(arr[1]));
//同上一样,也是错误代码
printf("%d\n", strlen(&arr));
//&arr取出整个数组的地址,类型是--char (*)[6],而strlen的参数类型是const char*,
//会有类型上的差异,但是依然可以运行,
printf("%d\n", strlen(&arr+1));
//&arr取出数组的地址,+1跳过数组,依然是随机值
printf("%d\n", strlen(&arr[0]+1));
//从第二个元素的地址开始,仍然是随机值


运行结果都是随机值:

image.png

char arr[] = "abcdef";
//a b c d e f \0
printf("%d\n", sizeof(arr));
//计算整个数组的大小,7
printf("%d\n", sizeof(arr+0));
//表示首元素地址,大小4/8个字节
printf("%d\n", sizeof(*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));
//取出第一个元素的地址,+1就是第二个元素的地址,那么就是4/8个字节

image.png

char arr[] = "abcdef";
//a b c d e f \0
printf("%d\n", strlen(arr));
//表示首元素地址,统计\0之前的字符,结果是6
printf("%d\n", strlen(arr+0));
//首元素地址+0还是首元素地址,结果还是6
printf("%d\n", strlen(*arr));//err
//*arr表示第一个元素,会报错
printf("%d\n", strlen(arr[1]));//err
//同上的道理,传进去的是第二个元素的ASCII码值
printf("%d\n", strlen(&arr));
//取出的数组的地址,结果也是6
printf("%d\n", strlen(&arr+1));
//&arr+1跳过整个数组,把\0也跳过,结果就是随机值
printf("%d\n", strlen(&arr[0]+1));
//表示第二个元素的地址,结果是5

image.png

char* p = "abcdef";
//把a的地址存到指针变量p中
printf("%d\n", sizeof(p));
//4/8,计算的是指针变量的大小
printf("%d\n", sizeof(p + 1));
//p+1指向第二个元素,存的是第二个元素的地址,就是4/8个字节
printf("%d\n", sizeof(*p));
//*p是第一个元素,大小是1个字节
printf("%d\n", sizeof(p[0]));//p[0]==*(p+0)--->*p
//也是第一个元素,大小是1个字节
printf("%d\n", sizeof(&p));
//取出的是p的地址,大小也是4/8个字节,p的地址的类型是char**,是二级指针
printf("%d\n", sizeof(&p + 1));
//&p是地址,+1还是地址,是地址就是4/8个字节
//需要理解的是:&p+1指向哪里?跳过一个p的大小
printf("%d\n", sizeof(&p[0] + 1));
//表示的是第二个元素的地址,是地址就是4/8个字节
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));
//&p的地址,无法确定有没有\0,是随机值
printf("%d\n", strlen(&p + 1));
//随机值,这里不再过多解释
printf("%d\n", strlen(&p[0] + 1));
//5

image.png


目录
相关文章
|
2月前
使用指针访问数组元素
【10月更文挑战第30天】使用指针访问数组元素。
40 3
|
2月前
|
存储 程序员 编译器
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
|
2月前
|
存储 C语言 计算机视觉
在C语言中指针数组和数组指针在动态内存分配中的应用
在C语言中,指针数组和数组指针均可用于动态内存分配。指针数组是数组的每个元素都是指针,可用于指向多个动态分配的内存块;数组指针则指向一个数组,可动态分配和管理大型数据结构。两者结合使用,灵活高效地管理内存。
|
2月前
|
容器
在使用指针数组进行动态内存分配时,如何避免内存泄漏
在使用指针数组进行动态内存分配时,避免内存泄漏的关键在于确保每个分配的内存块都能被正确释放。具体做法包括:1. 分配后立即检查是否成功;2. 使用完成后及时释放内存;3. 避免重复释放同一内存地址;4. 尽量使用智能指针或容器类管理内存。
|
2月前
|
存储 NoSQL 编译器
C 语言中指针数组与数组指针的辨析与应用
在C语言中,指针数组和数组指针是两个容易混淆但用途不同的概念。指针数组是一个数组,其元素是指针类型;而数组指针是指向数组的指针。两者在声明、使用及内存布局上各有特点,正确理解它们有助于更高效地编程。
|
19天前
|
存储 程序员 C++
深入解析C++中的函数指针与`typedef`的妙用
本文深入解析了C++中的函数指针及其与`typedef`的结合使用。通过图示和代码示例,详细介绍了函数指针的基本概念、声明和使用方法,并展示了如何利用`typedef`简化复杂的函数指针声明,提升代码的可读性和可维护性。
54 0
|
2月前
|
存储 人工智能 算法
数据结构实验之C 语言的函数数组指针结构体知识
本实验旨在复习C语言中的函数、数组、指针、结构体与共用体等核心概念,并通过具体编程任务加深理解。任务包括输出100以内所有素数、逆序排列一维数组、查找二维数组中的鞍点、利用指针输出二维数组元素,以及使用结构体和共用体处理教师与学生信息。每个任务不仅强化了基本语法的应用,还涉及到了算法逻辑的设计与优化。实验结果显示,学生能够有效掌握并运用这些知识完成指定任务。
61 4
|
2月前
使用指针访问数组元素
【10月更文挑战第31天】使用指针访问数组元素。
53 2
|
2月前
|
算法 索引
单链表题+数组题(快慢指针和左右指针)
单链表题+数组题(快慢指针和左右指针)
41 1
|
3月前
|
人工智能 前端开发 JavaScript
拿下奇怪的前端报错(一):报错信息是一个看不懂的数字数组Buffer(475) [Uint8Array],让AI大模型帮忙解析
本文介绍了前端开发中遇到的奇怪报错问题,特别是当错误信息不明确时的处理方法。作者分享了自己通过还原代码、试错等方式解决问题的经验,并以一个Vue3+TypeScript项目的构建失败为例,详细解析了如何从错误信息中定位问题,最终通过解读错误信息中的ASCII码找到了具体的错误文件。文章强调了基础知识的重要性,并鼓励读者遇到类似问题时不要慌张,耐心分析。

推荐镜像

更多