指针的学习5
目录
sizeof和strlen的区别
sizeof
strlen
数组和指针笔试题解析
一维数组
字符数组
二维数组
指针运算笔试题解析
题目1:
题目2:
题目3:
题目4:
题目5:
题目6:
题目7:
sizeof和strlen的区别
sizeof
sizeof计算变量所占内存空间的大小,单位是字节,如果操作数是类型的话,计算的是使用类型创建的变量所占内存空间的大小
sizeof只关注占用内存空间的大小,不在乎内存中存放什么数据
sizeof是单目操作符,不是函数!!!
#include <stdio.h>
int main()
{int a = 0;printf("%zd\n", sizeof(a));//4printf("%zd\n", sizeof(int));//4printf("%zd\n", sizeof a);//4——侧面证明了sizeof不是函数!函数调用要有括号return 0;
}
sizeof后面的()不进行计算!
int b = 8;short s = 4;printf("%d\n", sizeof(s = b + 2));//2printf("%d\n", s);//4
C语言是编译型语言:test.c->编译->链接->test.exe->运行
strlen
strlen是C语言库函数(头文件是<string.h>),功能是求字符串长度,函数原型如下:
size_t strlen(const char* str);
统计的是从strlen函数的参数str中这个地址开始向后,\0之前字符串中字符的个数(不算\0)
strlen函数会一直向后找\0字符,直到找到为止,所以可能存在越界查找
size_t len = strlen("abc\0ef");printf("%zd\n", len);//3
const char* str = "abcdef";printf("%zd\n", strlen(str));//6
char arr[] = { 'a','b','c' };printf("%zd\n", strlen(arr));//随机值——找到\0
数组和指针笔试题解析
一维数组
#include <stdio.h>
int main()
{//数组名的理解://数组名是数组首元素的地址,但是有两个例外://sizeof(数组名)——数组名表示整个数组,计算的是整个数组的大小,单位是字节//&数组名——数组名表示整个数组,取出的是整个数组的地址int a[] = { 1,2,3,4 };//数组有4个元素printf("%zd\n", sizeof(a));//16=4*4printf("%zd\n", sizeof(a + 0));//4或8——a表示首元素地址,类型是int*, a+0还是首元素地址printf("%zd\n", sizeof(*a));//4——a是首元素的地址,*a就是首元素,大小是4个字节,*a==a[0]=*(a+0)printf("%zd\n", sizeof(a + 1));//4或8——a表示首元素地址,类型是int*,a+1就是第二个元素的地址printf("%zd\n", sizeof(a[1]));//4——第二个元素printf("%zd\n", sizeof(&a));//4或8——整个数组的地址,是地址就是4或8printf("%zd\n", sizeof(*&a));//16——数组a的大小,*和&相抵消//&a是数组的地址,类型是int(*)[4],对数组指针解引用访问的是数组printf("%zd\n", sizeof(&a + 1));//4或8——&a+1是跳过整个数组后的那个位置的地址,是地址就是4/8,是野指针printf("%zd\n", sizeof(&a[0]));//4或8printf("%zd\n", sizeof(&a[0] + 1));//4或8——数组第二个元素的地址return 0;
}
字符数组
代码1:
#include <stdio.h>
int main()
{char arr[] = { 'a','b','c','d','e','f' };printf("%d\n", sizeof(arr));//6=6*1——计算数组大小printf("%d\n", sizeof(arr + 0));//4或8——数组首元素的地址,是地址就是4或8printf("%d\n", sizeof(*arr));//1——arr是首元素地址,*arr就是首元素,大小就是a的大小//*arr=arr[0]=*(arr+0)printf("%d\n", sizeof(arr[1]));//1——第二个元素的大小printf("%d\n", sizeof(&arr));//4或8——数组的地址printf("%d\n", sizeof(&arr + 1));//4或8——跳过整个数组得到的地址,指向数组后面的空间//&arr--char (*)[6]printf("%d\n", sizeof(&arr[0] + 1));//4或8——第二个元素的地址return 0;
}
代码2:
#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));//arr+0是数组首元素地址,数组中没有\0,导致越界访问,结果是随机的//printf("%d\n", strlen(*arr));这个代码有问题//err——首元素a的地址,'a'的ASCII码值是97,相当于把97作为地址传递给了strlen,strlen得到的就是野指针//printf("%d\n", strlen(arr[1]));//err——b的ASCII码值是98,同上printf("%d\n", strlen(&arr));//数组的地址,起始位置是数组的第一个元素的位置,结束位置随机xprintf("%d\n", strlen(&arr + 1));//跳过整个数组得到的地址,指向数组后面的空间,随机值x-6printf("%d\n", strlen(&arr[0] + 1));//从第二个元素开始向后统计,随机值x-1return 0;
}
代码3:
#include <stdio.h>
int main()
{char arr[] = "abcdef";printf("%d\n", sizeof(arr));//7printf("%d\n", sizeof(arr + 0));//4或8——arr表示数组首元素地址,arr+0还是数组首元素地址,是地址就是4或8printf("%d\n", sizeof(*arr));//1——arr是首元素地址,*arr就是首元素,大小就是a的大小//*arr=arr[0]=*(arr+0)printf("%d\n", sizeof(arr[1]));//1——第二个元素的大小printf("%d\n", sizeof(&arr));//4或8——数组的地址printf("%d\n", sizeof(&arr + 1));//4或8——跳过整个数组得到的地址,指向数组后面的空间//&arr--char (*)[6]printf("%d\n", sizeof(&arr[0] + 1));//4或8——第二个元素的地址return 0;
}
代码4:
#include <stdio.h>
#include <string.h>
int main()
{char arr[] = "abcdef";printf("%d\n", strlen(arr));//6printf("%d\n", strlen(arr + 0));//6——arr首元素的地址,arr+0还是首元素的地址,向后在\0之前有6个字符//printf("%d\n", strlen(*arr));//err——首元素a的地址,'a'的ASCII码值是97,相当于把97作为地址传递给了strlen,strlen得到的就是野指针//printf("%d\n", strlen(arr[1]));//err——b的ASCII码值是98,同上printf("%d\n", strlen(&arr));//6——数组的地址,起始位置是数组的第一个元素的位置printf("%d\n", strlen(&arr + 1));//跳过整个数组得到的地址,指向数组后面的空间,随机值printf("%d\n", strlen(&arr[0] + 1));//5return 0;
}
代码5:
#include <stdio.h>
int main()
{const 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——p的类型是const char*,*p就是char类型printf("%d\n", sizeof(p[0]));//1——第一个元素的大小printf("%d\n", sizeof(&p));//4或8——数组的地址printf("%d\n", sizeof(&p + 1));//4或8——跳过p指针变量后的地址,是地址就是4或8printf("%d\n", sizeof(&p[0] + 1));//4或8——第二个元素的地址return 0;
}
代码6:
#include <stdio.h>
#include <string.h>
int main()
{char* p = "abcdef";printf("%d\n", strlen(p));//6printf("%d\n", strlen(p + 1));//5//printf("%d\n", strlen(*p));//err——首元素a的地址,'a'的ASCII码值是97,相当于把97作为地址传递给了strlen,strlen得到的就是野指针//printf("%d\n", strlen(p[0]));//err——b的ASCII码值是98,同上printf("%d\n", strlen(&p));//&p是指针变量p的地址,与字符串无关//从p这个指针变量的起始位置开始向后数,p变量存放的地址是什么,不知道,所以答案是随机值printf("%d\n", strlen(&p + 1));//跳过整个数组得到的地址,指向数组后面的空间,随机值(与上句无关,因为有可能存在\0)printf("%d\n", strlen(&p[0] + 1));//5return 0;
}
二维数组
#include <stdio.h>
int main()
{int a[3][4] = { 0 };printf("%d\n", sizeof(a));//48——a是数组名,单独放在sizeof内部,计算的是整个数组的大小,单位是字节48=3*4*4printf("%d\n", sizeof(a[0][0]));//4——第一行第一个元素的大小printf("%d\n", sizeof(a[0]));//16——a[0]第一行的数组名,数组名单独放在sizeof内部了,计算的是数组的总大小16个字节printf("%d\n", sizeof(a[0] + 1));//4或8——a[0]第一行的数组名,但是a[0]并没有单独放在sizeof内部//a[0]就是数组首元素的地址,就是&a[0][0],a[0]+1即第一行第二个元素a[0][1],大小是4或8个字节printf("%d\n", sizeof(*(a[0] + 1)));//4——a[0][1]的大小printf("%d\n", sizeof(a + 1));//4或8——第二行地址的大小,a+1是数组指针,是地址大小就是4或8printf("%d\n", sizeof(*(a + 1)));//16——第二行的大小16=4*4printf("%d\n", sizeof(&a[0] + 1));//4或8——第一行第二个元素的地址,&a[0]就是数组第一行的地址,&a[0]+1就是第二行的地址printf("%d\n", sizeof(*(&a[0] + 1)));//16——第二行的大小printf("%d\n", sizeof(*a));//16——数组第一行的大小;*a==*(a+0)==a[0]printf("%d\n", sizeof(a[3]));//16——int [4],16=4*4;a[3]无需真实存在,仅仅通过类型的推断就能算出长度//a[3]是第四行的数组名,单独放在sizeof内部,计算的是第四行的大小,16个字节
}
指针运算笔试题解析
题目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));//2,5return 0;
}
题目2:
#include <stdio.h>
//在X86环境下(32环境)
//假设结构体的大小是20个字节
//程序输出的结果是?
struct Test
{int Num;char* pcName;short sDate;char cha[2];short sBa[4];
}*p = (struct Test*)0x100000;//结构体指针
//指针+-整数
int main()
{//0x1就是1printf("%p\n", p + 0x1);//00100014——结构体指针+1,要跳过整个结构体;0x100000+20->0x100014printf("%p\n", (unsigned long)p + 0x1);//00100001——不再是指针,long类型,整型值+1就是+1,0x100000+1->0x100001printf("%p\n", (unsigned int*)p + 0x1);//00100004——int*占4个字节return 0;
}
题目3:
#include <stdio.h>
int main()
{int a[3][2] = { {0,1},{2,3},{4,5} };int* p;p = a[0];printf("%d", p[0]);//0return 0;
}
#include <stdio.h>
int main()
{int a[3][2] = { (0,1),(2,3),(4,5) };//逗号表达式,即{1, 3, 5},后面元素用0来填充int* p;p = a[0];printf("%d", p[0]);//1return 0;
}
题目4:
#include <stdio.h>
int main()
{int a[5][5];int(*p)[4];//p是一个数组指针,指向的数组是4个整型元素p = a;printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);//FFFFFFFC,-4//a的类型:int (*)[5];p的类型是int (*)[4],一行四个元素//p[4][2]==*(*(p+4)+2)//两个指针之间相差4个元素//指针-指针的绝对值是指针和指针之间的元素个数return 0;
}
题目5:
#include <stdio.h>
int main()
{int aa[2][5] = { 1,2,3,4,5,6,7,8,9,10 };int* ptr1 = (int*)(&aa + 1);//强制类型转换为int*int* ptr2 = (int*)(*(aa + 1));//*(aa+1)==aa[1],aa[1]是第二行的数组名,数组名表示首元素的地址,aa[1]也是&aa[1][0]printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));//10,5return 0;
}
题目6:
#include <stdio.h>
int main()
{char* a[] = { "work","at","alibaba" };//数组的每个元素都是char*,a是指针数组char** pa = a;pa++;printf("%s\n", *pa);//atreturn 0;
}
题目7:
#include <stdio.h>
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——cpp+1,指向c+2printf("%s\n", *-- * ++cpp + 3);//ER——复杂!+优先级最低,cpp+1+1解引用指向c+1,c+1-1即为c,解引用得到"ENTER"首字母,首字母+3得到ERprintf("%s\n", *cpp[-2] + 3);//ST——*cpp[-2]+3即**(cpp-2)+3,cpp+2-2=cpp,指向c+3,指向FIRST,+3得到STprintf("%s\n", cpp[-1][-1] + 1);//EW——cpp[-1][-1]=*(*(cpp-1)-1);cpp+2-1=cpp+1,指向c+2,c+2-1=c+1指向NEW,+1得到EWreturn 0;
}

相关文章:
指针的学习5
目录 sizeof和strlen的区别 sizeof strlen 数组和指针笔试题解析 一维数组 字符数组 二维数组 指针运算笔试题解析 题目1: 题目2: 题目3: 题目4: 题目5: 题目6: 题目7: sizeof和…...
Dynamo——常用几何形体的创建与编辑(二)
上一次,我们简单整理了一些创建几何形体的节点用法,今天我们接着整理一些,几何形体的编辑方法。 一、坐标点的平移复制 [Point.Add] 使用节点 “Vector.ByCoordinates” 生成一个向量,将该向量连接到 “Point.Add” 节点的输入端 …...
uniapp富文本编辑-editor-vue2-vue3-wangeditor
前言 不管vue2还是vue3,都推荐官方的editor组件, 官方手册 https://uniapp.dcloud.net.cn/component/editor.html除了“微信小程序”,其他小程序想要使用editor组件实现富文本编辑,很难 第三方组件wangeditor在vue2࿰…...
【java】22:try-catch 异常处理
try-catch 方式处理异常说明 public static void main(String[] args) { int num1 10; int num2 0; try { int res num1 / num2; } catch (Exception e) { System.out.println(e.getMessage()); } } 注意事项 1)如果异常发生了,则异常发生后面的代码不会执行&…...
【C语言】linux内核ip_local_out函数
一、讲解 这个函数 __ip_local_out 是 Linux 内核网络子系统中的函数,部分与本地出口的 IPv4 数据包发送相关。下面讲解这段代码的每一部分: 1. 函数声明 int __ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb): -…...
动态规划6,最大数组和,环形子数组最大和,乘积最大子数组
最大子数组和 思路: 1.经验题目要求 dp[i]表示:以 i 位置为结尾的所有子数组中的最大和 2.状态转移方程 按长度来划分,如果长度为1,那么dp[i] nums[i]; 如果长度大于1,那么当前位置的最大和就为 i-1 位置最大和 …...
js 清空数组的方法
1、直接赋值空数组 let array [1, 2, 3, 4, 5]; array []; 这种方法并不推荐,如下图所示: 虽然a数组确实变为了空数组,但这种方法只是修改了a的指向,把a指向一个新的空数组,然而[1,2,3,4,5]这个数组并没有被清除&a…...
QT中使用QProcess执行命令,实时获取数据,例如进度条
前言 因为之前写了一个接收和发送文件的脚本,然后又需要获取进度,同步到进度条中。 效果: 使用正则匹配,获取命令行命令中的以下数据,然后同步到进度条 源码demo: 非完整代码: #include <Q…...
绘图设计:用Draw.io绘制图形技巧大全(含统一建模语言UML模板)
一、常见UML模板 1.流程图 2.用例图 include是包含关系,extend是扩展关系 简而言之,include是子集指向父集;而extend是扩展用例指向基础用例(基础用例可以理解为系统核心功能,扩展用例是可选的,不是必须…...
被唤醒的“第二十条”深入人心
近来张艺谋执导的电影《第二十条》,因为它与正在召开中的全国两会所发布的《最高人民法院工作报告》联系相当紧密,加之可免费收看,网民便相互转告,于是此信息条目立即冲上了网络热搜榜,观者如潮。因为最高人民法院工作…...
PHPInfo()信息泄漏原理以及修复方法
漏洞名称:PHPInfo信息泄漏、phpinfo()函数信息泄漏 漏洞描述: phpinfo()函数返回的信息中包含了服务器的配置信息,包括: 1)PHP编译选项以及文件扩展名的相关信息; 2)php的版本信息 3&#…...
202441读书笔记|《笠翁对韵》—— 金菡萏,玉芙蓉,酒晕微酡琼杏颊,香尘浅印玉莲双
202441读书笔记|《笠翁对韵》——金菡萏,玉芙蓉,酒晕微酡琼杏颊,香尘浅印玉莲双 《作家榜名著:笠翁对韵》作者李渔,霍俊明。是所有词句都有注音的一本书,轻松学不认识的字,非常朗朗上口的对偶词…...
006-v-model原理
v-model原理 简介v-model应用在输入框上v-model应用在组件上 简介 由 属性绑定(v-bind:value“searchText”) 配合 input事件监听(v-on:input“searchText event.target.value”) 实现。 应用在组件上由 props: {value: xxx } ,this.$emit(‘input’, xxx ) 完成。…...
Ubuntu下使用DAPLink(OpenOCD)
目录 1. 下载OpenOCD源代码 2. 编译代码 2.1 运行bootstrap 2.2 安装关联库 2.3 运行./configure 2.4 运行make 2.5 运行sudo make install 3. 烧录程序 3.1 挂起MCU 3.2 写入镜像 3.3 校验镜像 通过OpenOCD实现,在Ubuntu18 64bit下验证。 1. 下载OpenOC…...
C# 中 Math.Round 数学函数
在 C# 中,Math.Round 是一个数学函数,用于对一个浮点数进行四舍五入操作。它接受一个浮点数作为输入,并返回一个最接近输入值的整数或指定小数位数的浮点数。 Math.Round 方法有多个重载,其中最常用的重载有以下两种形式…...
力扣---接雨水---单调队列
题目: 单调队列思想: 没有思路的小伙伴可以先把这个想清楚哦:力扣hot10---大根堆双端队列-CSDN博客 从上面的图就可以发现,如果柱子呈递减序列,那么不会接到雨水,只要有一个小凸起柱子,那么这个…...
微分学<4>——微分中值定理
索引 微分中值定理极值定义4.1 极大(小)值定理4.1 Fermat引理定理4.2 Rolle定理 Lagrange中值定理定理4.3 Lagrange中值定理定理4.4 Cauchy中值定理 导数对函数性质的刻画Jensen不等式 微分中值定理 极值 定义4.1 极大(小)值 若存在 x 0 x_{0} x0的邻域 U ( x 0 , δ ) U\…...
FPGA的时钟资源
目录 简介 Clock Region详解 MRCC和SRCC的区别 BUFGs 时钟资源总结 简介 7系列FPGA的时钟结构图: Clock Region:时钟区域,下图中有6个时钟区域,用不同的颜色加以区分出来 Clock Backbone:从名字也能看出来&#x…...
LeetCode27: 移除元素
题目描述 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。 不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。 元素的顺序可以改变。你不需要考虑数组中超出…...
Python使用Beautiful Soup及解析html获取元素并提取内容值
Python使用Beautiful Soup及解析html获取元素并提取内容值 1. 包括解析获取标题2. 根据标签及id获取所有元素3. 根据标签及class获取所有元素4. 获取元素下的标签的值5. 获取元素下的parent及child的元素的值参考 1. 包括解析获取标题 2. 根据标签及id获取所有元素 3. 根据标…...
【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...
【Linux手册】探秘系统世界:从用户交互到硬件底层的全链路工作之旅
目录 前言 操作系统与驱动程序 是什么,为什么 怎么做 system call 用户操作接口 总结 前言 日常生活中,我们在使用电子设备时,我们所输入执行的每一条指令最终大多都会作用到硬件上,比如下载一款软件最终会下载到硬盘上&am…...
沙箱虚拟化技术虚拟机容器之间的关系详解
问题 沙箱、虚拟化、容器三者分开一一介绍的话我知道他们各自都是什么东西,但是如果把三者放在一起,它们之间到底什么关系?又有什么联系呢?我不是很明白!!! 就比如说: 沙箱&#…...
DiscuzX3.5发帖json api
参考文章:PHP实现独立Discuz站外发帖(直连操作数据库)_discuz 发帖api-CSDN博客 简单改造了一下,适配我自己的需求 有一个站点存在多个采集站,我想通过主站拿标题,采集站拿内容 使用到的sql如下 CREATE TABLE pre_forum_post_…...
Mysql故障排插与环境优化
前置知识点 最上层是一些客户端和连接服务,包含本 sock 通信和大多数jiyukehuduan/服务端工具实现的TCP/IP通信。主要完成一些简介处理、授权认证、及相关的安全方案等。在该层上引入了线程池的概念,为通过安全认证接入的客户端提供线程。同样在该层上可…...
深入解析光敏传感技术:嵌入式仿真平台如何重塑电子工程教学
一、光敏传感技术的物理本质与系统级实现挑战 光敏电阻作为经典的光电传感器件,其工作原理根植于半导体材料的光电导效应。当入射光子能量超过材料带隙宽度时,价带电子受激发跃迁至导带,形成电子-空穴对,导致材料电导率显著提升。…...
