《每天一分钟学习C语言·七》指针、字节对齐等

1、
对于二维数组如a[3][4]可以当做有三个元素的一维数组,每个元素包含四个小元素。

2、
printf(“%-5d”, i); //负号表示左对齐,5d表示空五个光标的位置

3、
栈:先进后出,堆:先进先出

4、
(1)int * p; //p是指针变量名字, int *表示p变量存放的是int类型的地址,p = &i; // 把i地址赋给了p,此时p指向i, * p为p指向的地址存放的变量,即 * p为i的整型变量的值。
(2)指针就是地址,地址就是指针,地址就是内存单元的编号
(3)指针变量就是存放地址的变量
(4)CPU可以直接操控内存条
(5)int *p; * p=3; //错误,因为指针变量p没有初始化
(6)int * p; //没有给指针变量初始化,p指向内存单元随意一个编号,这种情况下是不能读写随意编号里面存放的内容的,则输出 * p错误,比如随意指向了电脑图库的地址,如果能随意读写就侵犯隐私了。
(7)假如指针变量p,q同时指向一个地址,那free( p);表示p指向的空间被释放,不能在free(q);,因为p,q指向同一个空间,这个空间已经在free( p)的时候已被释放,如果没有被释放,那这个内存的空间就会被一直占有,会容易导致内存泄漏;
(8)int * p = (int * )malloc(4); //动态分配四个字节内存空间,返回第一个字节地址给p,即p指向第一个字节的地址。之所以强制类型转换就是告诉P指向的地址是保存整型变量的地址。系统总共分配了8个字节的空间,静态分配指针变量p占4个字节,p指向的动态分配的内存空间占4个字节,一共8个。Free( p)表示把p指向的动态分配的内存空间给释放掉,但p本身的内存不会释放,因为p内存是静态分配的,这需要等函数执行结束由系统释放。
(9)静态内存都是在栈里分配的,动态内存在堆里分配
(10)int ** p中p存放的是地址的地址,如int i = 3; int * q = &i; p = &q;
则 * p == q,又 * q == i,所以**p == i

5、
指针和数组
(1)数组名是第一个元素的地址,则p[0] == *p p[i] == *(p+i)
(2)数组是连续的
(3)a[2]; b[2]; a = b //error,数组名是指针常量,常量不可以被赋值
(4)

void f(int a[])
{int i;int j = sizeof(a);printf("%d\n", j); //长度为4/*for(i=0; i<sizeof(p)/sizeof(*p); i++)printf("%d\n", *(p+i));*/
}int main(void)
{int a[5] = {1, 2, 3, 4, 5};printf("%d\n", sizeof(a)); //长度为20f(a);getchar();return 0;
}

主函数输出长度为20,自定义函数输出长度为4,那是因为把数组名传入自定义函数就自动转化为指针的形式进行操作,而指针的长度32位系统固定为4,64位系统固定为8(注意:32位系统和64位系统中编译器为了相互兼容指针都占4个字节)
(5)如果两个指针变量指向的是同一个连续空间不同的存储单元,这两个指针可以相减,比如在数组里。
(6)一个变量的地址比如1001H地址里面存放3这个整型,这个1001H是整型的首个字节的地址,因为整型有四个字节,而指针指向的变量的地址都是首地址。
(7)动态定义一维数组

int len;
int i;
int * p;printf("输入一维数组的长度:");
scanf("%d", &len);
p = (int *)malloc(len * 4); //给p指向的空间分配len*4个字节空间,假如len = 4;//*p为前四个字节存放的整型,*(p+1)为后四个字节存放的整型,*(p+2)为后后四个字节存放的整型//*(p+3)为最后一组四个字节存放的整型
//给动态数组赋值
*p = 1;
p[1] = 2; //*(p+1) == p[1]
*(p+2) = 3;
*(p+3) = 4;for(i=0; i<4; i++)printf("%d\n", *(p+i)); //1 2 3 4
free(p);

6、
指针的一个不容易想通的问题,以后指针出问题就看这个例子

int main(void)
{int i = 2;int * p;f1(p);printf("%d\n", *p);getchar();return 0;
}void f1(int * q)
{*q = 3;
}

显示结果错误,p没有初始化,随意的指向了内存的一个空间,又把这个地址给了q,及p,q指向了一个相同的内存空间,*q修改了这个内存空间的内容是错误的,不确定的一个内存空间的内容是无法读写的。

第二种:

int main(void)
{int i = 2;int * p = &i;f1(p);printf("%d\n", *p);getchar();return 0;
}void f1(int * q)
{q = (int *)malloc(4);*q = 3;
}

输出答案是2不是3,首先p指向i的地址,则p == 2,把p地址赋给q,则p,q共同指向i地址,这时若q = 3,则i的值会变。但在函数里却给q分配了一个新的内存空间,这时q指向这个动态内存空间,跟p没关系,p依然指向i地址,这时p=3不会影响i的值,所以p依然为2

第三种:

int main(void)
{int i = 2;int * p = &i;f1(&p);printf("%d\n", *p);free(p);getchar();return 0;
}void f1(int ** q)
{*q = (int *)malloc(4);**q = 3;
}

答案为3不是2,首先把i地址赋给p,这时p指向i地址,p==2。然后把p地址的地址赋给q,这时q指向p地址的地址,q便是p地址,修改q的值便是修改p地址,这时若给q申请一个内存空间,那么q和p都指向这个内存空间,p不在指向i地址,这时给**q赋值,就是把q和p共同指向的内容空间放入值,那么*p就是这个值,用完要释放这个内存空间。

7、
结构体和联合体
struct student
{

};
struct student是一个数据类型,int ,double…也是一个数据类型。
struct student st; //定义一个struct student类型的变量st
两种赋值方式:struct student st = {50, 34.2f, ‘F’};
st.age = 20; st.score = 34.3f; st.sex = ‘F’;
第二种取值方式:struct student * pst = &st; //把st地址赋给pst,即pst指向st地址。printf(“%d\n”, pst->age); //20 pst->age = 10; //因pst指向的内存空间为st的内存空间,所以修改pst->age的值即st.age值也会变。另一个写法(*pst).age

(2)结构体占多少个字节数?
涉及到字节对齐,(需要字节对齐的根本原因在于CPU访问数据的效率问题)总的字节数必须是结构体中最大成员变量字节数的整数倍,前一个成员变量必须是后一个成员变量字节的整数倍,不足自动补齐。(注:结构体首地址是第一个成员地址)如

struct student
{int num;doube mark;char name;
}

int占四个字节,double占八个字节,所以int自动补齐四个字节一共八个字节是double整数倍,这时一共4+4+8=16个字节是char字节数的整数倍,这时总字节数为4+4+8+1=17不满足是最大成员变量double字节数的整数倍,故在自动补齐7个字节,这时一共是24个字节。sizeof(struct student) == 24

struct student
{char ch[5];short k[3];char arr[9];
}

整除是整除的数据类型。5不能被short(2)整除,故5+1
5+1+6=12可以被char(1)整除
12+9=21不能被最大数据类型short(2)整除,故21+1=22

union uni
{struct s{short a[5];};double i;char a[9];
};

注意:联合体中如果有结构体,字节对齐时会忽略结构体的存在,相当于联合体中只有double i和char a[9],或者如果结构体中有结构体,字节对齐时会忽略这个结构体的存在。
先找最大宽度字节数为9, 9不能被double(8)整除,故9+7=16
16既能被char整除又能被double整除

union uni
{char a[11];short i[3];double k[2];
};

先找最大宽度字节16,16能被char(1)整除,然后16又能被short(2)整除,能被double整除,故为16

还有一种情况:

struct st2 {double i;
};struct st1 {struct st2 st;int i;
};

printf(“%d\n”, sizeof(struct st1)); //这种情况会把嵌套的结构体字节数算进去,嵌套结构体字节数为8,则8+4+4 = 16是最大数据类型double (8)的倍数

union uni
{char a[11];short i[3];double k[2];
};struct student {union uni u;int j;
}st;

联合体字节数:16,结构体总字节数:16+4+4=24是最大数据类型double (8)的倍数

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/238829.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

位运算:Leetcode137.只出现一次的数字(2)

题目描述&#xff1a; 给你一个整数数组 nums &#xff0c;除某个元素仅出现 一次 外&#xff0c;其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。 示例 1&#xff1a; 输入&#xff1a;nums [2,2,3,2] 输出&#xff1a;3示例 2&#xff1a; 输入&…

《工具箱-SVN》SVN安装、备份、迁移教程

文章目录 一、服务器搭建SVN1.检查SVN是否存在2.安装SVN3.创建版本库4.创建版本库存放文件地址5.修改配置文件5.1 vim authz5.2 vim passwd5.3 vim svnserve.conf 6.启动并查看SVN7.SVN Checkout8.SVN Update9.SVN Commit 二、SVN-无法连接主机&#xff0c;目标计算机积极拒绝&…

案例 | 电源自动检测测试系统为某电子科技公司定制电源测试解决方案

一、测试背景 陕西某电子科技公司是一家专业生产设计军品电源、集成电路以及电子元器件的高新技术企业&#xff0c;公司虽有一套半自动ATE测试系统&#xff0c;但使用过程繁琐复杂且无法满足日益增长的测试需求&#xff0c;因此公司现需要一套更加优秀的全自动电源测试系统来应…

工具系列:PyCaret介绍_多分类代码示例

&#x1f44b; 工具系列&#xff1a;PyCaret介绍_多分类代码示例 PyCaret 介绍 PyCaret是一个开源的、低代码的Python机器学习库&#xff0c;可以自动化机器学习工作流程。它是一个端到端的机器学习和模型管理工具&#xff0c;可以大大加快实验周期并提高生产效率。 与其他开…

HDFS NFS Gateway(环境配置,超级详细!!)

&#x1f42e;博主syst1m 带你 acquire knowledge&#xff01; ✨博客首页——syst1m的博客&#x1f498; &#x1f618;《CTF专栏》超级详细的解析&#xff0c;宝宝级教学让你从蹒跚学步到健步如飞&#x1f648; &#x1f60e;《大数据专栏》大数据从0到秃头&#x1f47d;&…

【论文阅读】FreeU: Free Lunch in Diffusion U-Net

FreeU: 无需训练直接提升扩散模型生成效果。 paper&#xff1a;https://arxiv.org/abs/2309.11497 code&#xff1a;GitHub - ChenyangSi/FreeU: FreeU: Free Lunch in Diffusion U-Net 1. 介绍 贡献&#xff1a; •研究并揭示了U-Net架构在扩散模型中去噪的潜力&#xff0…

Redis单机、主从、哨兵、集群配置

单机配置启动 Redis安装 下载地址&#xff1a;Download | Redis 安装步骤&#xff1a; 1: 安装gcc编译器&#xff1a;yum install gcc 2: 将下载好的redis‐5.0.3.tar.gz文件放置在/usr/local文件夹下&#xff0c;并解压redis‐5.0.3.tar.gz文件 wget http://download.re…

react生命周期详解,代码示例(新生命周期,与旧生命周期对比)

旧生命周期&#xff1a;https://blog.csdn.net/kkkys_kkk/article/details/135130549?spm1001.2014.3001.5501 目录 React 生命周期中常见的坑 为什么要移除 “will” 相关生命周期方法呢&#xff1f; Fiber是什么 新生命周期图示 新增生命周期与功能变化 完整生命周期…

C语言操作符详解+运算符优先级表格

目录 前言 一、操作符是什么&#xff1f; 二、操作符的分类 三、算术操作符 四、逻辑操作符 五、比较操作符 六、位操作符 七、赋值操作符 八、其他操作符 九、运算符优先级表格 总结 前言 在编写程序时&#xff0c;最常用到的就是操作符&#xff0c;本文将详细的介绍…

Golang 的内存管理

文章目录 1.内存管理角色1.常见的内存分配方法线性分配器空闲链表分配器TCMalloc 2.Go 内存管理组件mspanmcache初始化替换微分配器 mcentralmheap 3.内存分配4.内存管理思想参考文献 1.内存管理角色 内存管理一般包含三个不同的组件&#xff0c;分别是用户程序&#xff08;Mu…

【C语言】指针详解(三)

1.指针运算 指针的基本运算有三种&#xff0c;分别是:⭐指针-整数 ⭐指针-指针 ⭐指针的关系运算 1.1指针 - 整数 因为数组在内存中是连续存放的&#xff0c;只要知道第一个元素的地址&#xff0c;顺藤摸瓜就能找到后面的所有元素。 int arr[10]{1,2,3,4,5,6,7,8,9,10} #inc…

劈窗算法反演地表温度

目录 摘要操作步骤提取热红外单波段提取NDVI同步像元分辨率与个数劈窗算法地表温度反演制图 摘要 主要使用HJ-2&#xff08;环境减灾二号卫星&#xff09;的IRS传感器的两个热红外波段&#xff0c;以及红波段与近红波段计算得到的NDVI&#xff0c;使用劈窗算法&#xff0c;得到…

贪吃蛇(五)蛇撞墙

上节我们实现了蛇身向右移动的功能&#xff0c;原理就是增加一个节点&#xff0c;删除一个节点。 本节我们处理蛇撞墙重置的功能 实现原理 在移动函数中检查蛇头&#xff08;链表尾节点&#xff09;是否达到墙边的坐标&#xff0c;这里有四种撞墙的情况&#xff1a; 上墙&am…

使用Docker-镜像命令

镜像名称一般分两部分组成:[repository]:[tag] 在没有指定tag时&#xff0c;默认是latest&#xff0c;代表最新版本的镜像 案例一&#xff1a;从DockerHub中拉取一个nginx镜像并查看 1.1. 首先去镜像仓库搜索nginx镜像&#xff0c;比如DockerHub 点击nginx 复制拉取命令 1.2.…

MySQL中替换字符串中的指定部分之REPLACE函数

REPLACE函数是用来替换字符串中的指定部分内容的。在本文中&#xff0c;将介绍如何在MySQL中使用REPLACE函数进行字符串替换 REPLACE函数的语法&#xff1a; REPLACE(str, search_str, replace_str) 其中&#xff0c;str是要进行替换操作的字符串&#xff0c;search_str是要搜…

使用Mosquitto/python3进行MQTT连接

一、简介 MQTT(消息队列遥测传输)是ISO 标准(ISO/IEC PRF 20922)下基于发布/订阅范式的消息协议。它工作在 TCP/IP协议族上&#xff0c;是为硬件性能低下的远程设备以及网络状况糟糕的情况下而设计的发布/订阅型消息协议&#xff0c;为此&#xff0c;它需要一个消息中间件。 …

【CMake保姆级教程】制作动静态链接库、指定动静态库输出路径

文章目录 前言一、动静态链接库的介绍1.1 动态链接库 (DLL)1.2 静态链接库 (LIB) 二、制作静态库三、制作动态库四、指定动静态库输出路径4.1 方式1 - 适用于动态库4.2 方式2 - 都适用 总结 前言 在软件开发中&#xff0c;我们经常听到动态链接库&#xff08;Dynamic Link Lib…

[LitCTF 2023]PHP是世界上最好的语言!!

[LitCTF 2023]PHP是世界上最好的语言&#xff01;&#xff01; wp 进入页面&#xff0c;发现左边有输入框&#xff0c;下面有 RUN CODE 字样&#xff0c;估计是可以执行命令的。 执行 PHP 代码测试 <?php print(1); ?>将 PHP 一句话木马写入文件 为了蚁剑能连上&am…

全国30米分辨率逐年最大NDVI数据集

全国30米分辨率逐年最大NDVI数据集 中国30m逐年NDVI最大值数据集是基于Google Earth Engine&#xff08;GEE&#xff09;遥感云计算平台&#xff0c;利用美国陆地卫星Landsat 5/7/8/9遥感影像计算的1986年以来的逐年度NDVI最大值数据集。计算过程中对每年度全年所有的Landsat5/…

智能算力进阶C位,揭秘人工智能产业背后的“冰山一角”

作者 | 曾响铃 文 | 响铃说 前几年&#xff0c;在IDC领域&#xff0c;市场谈及最多的还是数据中心&#xff0c;随着人工智能产业的成熟&#xff0c;特别是今年以来大模型的爆发&#xff0c;智算中心逐步替代了数据中心进入大众视野&#xff0c;成为市场热议的关键词&#xff…