学习笔记2:指针经典代码阅读练习
目录
一.阅读下列代码分析输出结果:
画图分析:
二.阅读下列代码分析输出结果:
画图分析 :
三.阅读下列代码分析输出结果:
画图分析:
四.关于sizeof操作符的运用
一.阅读下列代码分析输出结果:
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);return 0;
}
初步分析:
&a-->得到的是数组指针:&+数组名得到的都是数组指针
比如: int arr[3][3];(二维数组的数组名是行指针);
arr本身的类型为:int (*)[3];
则&arr得到的指针类型为: int (*) [3][3]; 该指针的访问权限是9*sizeof(int)
运算单位(步长)也是9*sizeof(int);
因此这里&a得到的数据类型是 int (*) [4];
&a+1 地址值在数值上增加了sizeof(int)*4=16;
而(int)a则是将a的数据类型转化为整形,整形加一数值上只加一;
画图分析:
1. ptr[-1]的结果分析:
所以ptr[-1]的结果为4
2. *ptr2的结果分析
注意案例中的代码运行环境的数据存储方式是小端存储:
整形数据小端存储:数据的高位字节存储在高地址的内存中,数据的低位字节存储在低地址的内存中。(大端存储则是数据的高位字节存储在低地址的内存中,数据的低位字节存储在高地址的内存中)
a数组在内存的存储:
所以*ptr2的结果为 2000000
二.阅读下列代码分析输出结果:
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]);return 0;
}
%p表示以无符号十六进制整数的形式打印
初步分析:
a是二维数组的数组名,a的数据类型为:int (*)[5]
int(*)[5]类型的指针访问权限为sizeof(int)*5=20 字节(环境为vs2022),其运算单位(步长)也是20个字节
p的指针类型为 int (*)[4]
int (*)[4]类型的指针访问权限为sizeof(int)*4=16 字节,其运算单位(步长)也是16个字节
画图分析 :
注意 &p[4][2] - &a[4][2]得到 -4 :
-4在计算机内存中的存储的形式是二进制序列补码:
-4的原码:10000000000000000000000000000100
-4的反码:111111111111111111111111111111111011
-4的补码:111111111111111111111111111111111100 (反码加一得到补码)
因此如果以%p(无符号十六进制位数)的形式打印 -4 会直接按照-4的补码作为原码进行打印.因此得到的结果是 FFFFFFFC (32位机器)(64位机器结果为FFFFFFFFFFFFFFFC)
因此本题得到的结果为: FFFFFFFC,-4
三.阅读下列代码分析输出结果:
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;
}
画图分析:
注意字符串常量代表字符串常量的首地址(系统会在内存中为字符串常量开辟空间)
分析printf("%s\n", **++cpp):
因此 **++cpp得到的是"POINT"字符串常量的首地址
打印结果是POINT
(注意++cpp使cpp本身的值发生变化)
分析printf("%s\n", *-- * ++cpp + 3):
所以打印的结果为 ER
分析printf("%s\n", *cpp[-2] + 3):
所以打印的结果为:ST
分析printf("%s\n", cpp[-1][-1] + 1):
所以打印的结果为:EW
因此程序最终输出的结果为:
POINT
ER
ST
EW
四.关于sizeof操作符的运用
sizeof(数组名)--这里sizeof会计算整个数组的大小,单位是字节 (这里要求数组名要单独作为sizeof()的操作数,这时sizeof才会计算整个数组的大小)
其他的情况下sizeof的计算结果取决于操作数的类型
示例组一:
int a[4];
sizeof(a);这里a是数组名sizeof会计算整个数组的大小,返回值为16
sizeof(a+0);这里a+0表示第一个元素的地址,sizeof计算的是指针的大小
sizeof(*&a);这里的*&a与a等价,sizeof会计算整个数组的大小
sizeof(&a[0]); 这里的a[0]表示数组的第一个元素,&a[0]表示数组的首元素地址sizeof会计算指针的大小
示例组二:
int a[3][4];
二维数组int a[3][4]可以看成是由3个一维数组(每个一维数组四个元素)作为元素构成的,三个一维数组的数组名分别为a[0],a[1],a[2].
sizeof(a);这里数组名a单独作为操作数, sizeof计算整个二维数组a大小,结果为48
sizeof(&a[0]) :这里等价于(a+0),二维数组数组名没有单独放在sizeof内部,sizeof将计算指针变量的大小。
sizeof(a[0]);这里相当于将一维数组a[0]数组名单独作为操作数,sizeof计算的是一维数组a[0]的大小,结果为16
sizeof(a[0]+1); a[0]+1指向数组a第一行第二个元素,这里sizeof计算的是指针的大小
sizeof(a+1); a+1是一个数组指针,指向二维数组的第二行,这里sizeof计算的是指针的大小
sizeof(*(a+1)); *(a+1)相当于将一维数组a[1]数组名单独作为操作数,这里sizeof计算的是一维数组a[1]的大小,结果为16
sizeof(&a[0]+1); a[0]是二维数组a第一行首元素地址,&a[0]与a等价,是一个数组指针,类型为int (*)[4], &a[0]+1为二维数组a第二行的地址,这里sizeof计算的是指针的大小
sizeof(*(&a[0]+1));&a[0]+1为二维数组a第二行的地址,类型为int (*)[4],*(&a[0]+1)得到第二行首元素地址,相当于a[1],相当于将一维数组a[1]数组名单独作为操作数,这里sizeof计算的是一维数组a[1]的大小,结果为16
sizeof(*a);这里相当于将一维数组a[0]的数组名单独作为操作数,sizeof计算的是一维数组a[0]的大小,结果为16
sizeof(a[3]);这里相当于将一维数组a[3]的数组名单独作为操作数,sizeof计算的是一维数组a[3]的大小,结果为16
注意a[3]虽然是越界访问,但作为sizeof操作数的表达式在代码运行时并不会执行,所以sizeof(a[3])是可以计算出结果的。
小结:
1.sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小
2.&数组名,这里的数组名表示整个数组,取出的是整个数组的地址,类型为数组指针
3.除此之外所有数组名都表示首元素的地址。
另外:
作为sizeof的操作数的表达式只具有类型属性,在程序运行时不会执行作为sizeof操作数的表达式,sizeof的运算结果其实是在预处理阶段就已经给出了。
学习笔记2:指针经典代码阅读练习相关推荐
- python函数是一段具有特定功能的语句组_Python学习笔记(五)函数和代码复用
本文将为您描述Python学习笔记(五)函数和代码复用,具体完成步骤: 函数能提高应用的模块性,和代码的重复利用率.在很多高级语言中,都可以使用函数实现多种功能.在之前的学习中,相信你已经知道Pyth ...
- 梓益C语言学习笔记之指针
梓益C语言学习笔记之指针 一.32位平台下,地址是32位,所以指针变量占32位,共4个字节 二.内存单元的地址即为指针,存放指针的变量称为指针变量,故:"指针"是指地址,是常量,& ...
- Lasso线性回归学习笔记(公式与代码实现)
目录 Lasso线性回归学习笔记(公式与代码实现) 1 为什么要在线性回归中引入正则化项(简介) 2 常见正则化项 3 损失函数图像与正则化之后的图像 3.1损失函数图像 3.2 加了 L~1~ 正则 ...
- Windows保护模式学习笔记(二)—— 代码跨段跳转
Windows保护模式学习笔记(二)-- 代码跨段跳转 要点回顾 代码跨段跳转 执行流程 1)段选择子拆分 2)查表得到段描述符 3)权限检查 4)加载段描述符 5)代码执行 6)总结 一致代码段(共 ...
- JavaWeb黑马旅游网-学习笔记10【项目代码】
Java后端 学习路线 笔记汇总表[黑马程序员] JavaWeb黑马旅游网-学习笔记01[准备工作] JavaWeb黑马旅游网-学习笔记02[注册功能] JavaWeb黑马旅游网-学习笔记03[登陆和 ...
- 点云学习笔记11——VoxelNet算法+代码运行
点云学习笔记11--VoxelNet算法+代码运行 一.算法分析 摘要 介绍 相关工作 1.2. 贡献 2.VoxelNet 2.1.特征学习网络 2.1.1 特征学习网络 二.代码复现 2.1.环境 ...
- Unity学习笔记--赛车的控制代码
Unity学习笔记–赛车的控制代码 using System.Collections; using System.Collections.Generic; using UnityEngine;publ ...
- python基础代码事例-学习笔记:python3,代码。小例子习作(2017)
http://www.cnblogs.com/qq21270/p/7634025.html 学习笔记:python3,一些基本语句(一些基础语法的代码,被挪到这里了) 日期和时间操作 http://b ...
- C++学习笔记7[指针]
C++学习目录链接: C++学习笔记目录链接(持续更新中) 文章目录 一.变量和指针 1.指针的声明 2.指针的赋值 3.关于指针使用的说明 4.指针运算符和取地址运算符 5.指针运算 二.指针和数组 ...
最新文章
- matlab ros 手势识别,使用MATLAB读取分析ros记录的.bag文件
- 【PAT乙级】 1010 一元多项式求导 (25 分)
- 20个顶尖产品经理都在用的APP
- 协议层次及其服务模型
- 今年面试,光靠技术肯定不行了!
- 对996最客观的描述,一叶知秋
- php post数组丢失,php – 神秘空$_POST数组
- 云安全之虚拟机安全监控
- java 快速创建map_快速创建Map并初始化,超级简单
- CODEVS 3657 括号序列
- 有乐窝一周精选(二)
- python调用百度通用翻译API进行翻译
- 金额中文大写c语言,C语言编程:数字金额转换为中文大写金额?
- python连接S3
- 计算机应用越来越广泛翻译英文,越来越普遍英语,越来越普通的英文?
- 广达做微软服务器,微软联手广达布局云计算 称策略是软件加服务
- 分析一种简单的提高功率因数的电路——填谷电路
- loadrunner使用sitescope监测监控mysql数据库
- 100万美金VS100美金FBI本可以在iPhone 5c解锁案中省下一大笔钱
- Linux内核学习方法
热门文章
- c语言实例 魔术师的猜牌术(1),C语言实例:魔术师的猜牌术(1)
- c语言实例 魔术师的猜牌术(1),C语言实例 魔术师的猜牌术(1)
- 一个不错的网站,颜色推荐 http://www.colorhexa.com/
- TIA portal西门子博途中优化的DB块和标准DB块的区别
- 定位iowait问题
- mysql的blob字段存储中文,输出乱码
- Ubuntu 10.04 更新源(ubuntu yuan)
- LD链接脚本解析-STM32F4xx
- MTK Android 11 预装可卸载APP
- php mysql curd_使用PHP操作SQL 完成简单的CURD操作