《每天一分钟学习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)); //长度为20
	f(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)的倍数

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

零代码助力服装行业数字化转型

内容来自演讲&#xff1a;涂岳俊 | 广州市衣湛国际信息科技有限公司 | CEO 摘要 这篇文章讨论了为什么选择明道云零代码平台&#xff0c;以及它如何帮助服装企业解决各种问题。作者分享了自己的经验&#xff0c;并列举了一些成功的案例来证明零代码平台的优势。文章还提到了在…

分布式锁概述

一、概念 1、什么是分布式锁 我们知道传统进程内的多线程之间可以利用锁机制来实现它的同步&#xff0c;同时进程之间也可以互相通信&#xff0c;那我我们如果使用分布式服务的话&#xff0c;有应该怎么实现集群内多服务之间访问公共资源&#xff0c;并且确保它们不会出现问题…

RobotMaster学习——工序导入,参数设置,轨迹生成

目录 引出1.导入工序2.修改刀具其他刀具参数 3.进行工序分配4.设置TCP5.设置工作站6.工序整体导入配置7.进行计算 总结 引出 RobotMaster的操作流程&#xff0c;从导入工序到生产轨迹。 1.导入工序 2.修改刀具 要选择第七把刀具 其他刀具参数 第一把刀具 第二把刀具 第三把刀…

自制数据库空洞率清理工具-C版-01-EasyClean-V1.0(支持南大通用数据库Gbase8a)

目录 一、环境信息 二、简述 三、支持功能 四、空洞率 五、工具流程图 六、安装包下载地址 七、参数介绍 1、命令模板 2、命令样例 3、参数表格 八、安装步骤 1、配置环境变量 2、生效环境变量 3、检验动态链接是否正常 九、运行效果 一、环境信息 名称值CPUInt…

MySQL——内置函数

目录 一.日期函数 1.current_date() 2.current_time() 3.current_stamp() 4.date_add() 5.date_sub() 6.datediff 7.date 8.now 二.字符串函数 1.charset() 2.concat() 3.length() 4.replace 5.substring(str,postion,length) 6.instr&#xff08;string,substr…

基于ssm+jsp二手车估值与销售网络平台源码和论文

随着信息化时代的到来&#xff0c;管理系统都趋向于智能化、系统化&#xff0c;二手车估值与销售网络平台也不例外&#xff0c;但目前国内仍都使用人工管理&#xff0c;市场规模越来越大&#xff0c;同时信息量也越来越庞大&#xff0c;人工管理显然已无法应对时代的变化&#…

ansible-playbook的Temlates模块 tags模块 Roles模块

Temlates模块 jinja模板架构&#xff0c;通过模板可以实现向模板文件传参(python转义)把占位符参数传到配置文件中去,生产一个目标文本文件&#xff0c;传递变量到需要的配置文件当中 &#xff08;web开发&#xff09; nginx.conf.j2 早文件当中配置的是占位符&#xff08;声明…

vivado 自动派生时钟

自动派生时钟 自动派生的时钟也称为自动生成的时钟。Vivado IDE自动在时钟修改块&#xff08;CMB&#xff09;的输出引脚上创建这些的约束&#xff0c;只要已经定义了相关的主时钟。在AMD 7系列设备系列中&#xff0c;CMB有&#xff1a; •MMCM*/PLL* •BUFR •相位器* 在…

Spring源码分析 @Autowired 是怎样完成注入的?究竟是byType还是byName亦两者皆有

1. 五种不同场景下 Autowired 的使用 第一种情况 上下文中只有一个同类型的bean 配置类 package org.example.bean;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;Configuration public class FruitCo…

过度加大SSD内部并发何尝不是一种伤害-part2

方案设计完了&#xff0c;如何验证效果如何呢&#xff1f;作者是这么做的。 第一步&#xff0c;选择模拟环境&#xff1a;PLAN方案在定制的FEMU&#xff08;Flash Emulation Module&#xff09;上实现&#xff0c;该模块支持TRIM和多流功能&#xff0c;具体参数如下&#xff1…

modbus_tcp的实现 through python.

0.引言 当前科技似乎处于加速发展期&#xff0c;各个模块都在快速迭代&#xff0c;迭代的速度会让既有的一些经验产生问题&#xff0c;在用python实现modbus_tcp协议时&#xff0c;网上流传的一些代码中import语句会出现问题。导致pymodbus模块用起来很不好用。 这个原因出在…

基于YOLOv8深度学习的智能玉米害虫检测识别系统【python源码+Pyqt5界面+数据集+训练代码】目标检测、深度学习实战

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

react当中生命周期(旧生命周期详解)

新生命周期https://blog.csdn.net/kkkys_kkk/article/details/135156102?spm1001.2014.3001.5501 目录 什么是生命周期 react中的生命周期 旧生命周期 生命周期图示 常用的生命周期钩子函数 初始化阶段 挂载阶段 在严格模式下挂载阶段的生命周期函数会执行两次原因 更…

W25Q128

什么是 W25Q128 &#xff1f; W25Q128是一款由Winbond&#xff08;威邦电子&#xff09;公司生产的闪存存储器芯片&#xff0c;属于串行闪存系列。具体来说&#xff0c;W25Q128是一颗128Mb&#xff08;兆位&#xff09;容量的串行闪存芯片&#xff0c;其中"W"代表Wi…

Python匹配文件模块的实战技巧

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 在Python中&#xff0c;文件匹配是许多应用中常见的需求&#xff0c;例如文件管理、数据处理等。本文将深入探讨Python中用于文件匹配的模块&#xff0c;包括glob、fnmatch和os.path等&#xff0c;通过丰富的示例…

第11章 GUI Page403~405 步骤三 设置滚动范围

运行效果&#xff1a; 源代码&#xff1a; /**************************************************************** Name: wxMyPainterApp.h* Purpose: Defines Application Class* Author: yanzhenxi (3065598272qq.com)* Created: 2023-12-21* Copyright: yanzhen…

C# 跨越配置

跨越配置1 项目框架 .NET Framework 1.web.config配置 在system.webServer节点中添httpProtocol子节点 Access-Control-Allow-Origin值为“*”” <httpProtocol><customHeaders><add name"Access-Control-Allow-Origin" value"*" /><…

基于DeepSpeed对 llama2-7b的LORA精调

DeepSpeed数据并行研究 1. 技术调研 a. DeepSpeed DeepSpeed是一个开源深度学习训练优化库&#xff0c;其中包含一个新的显存优化技术—— ZeRO&#xff08;零冗余优化器&#xff09;。该框架包含四个技术亮点&#xff1a; 用 3D 并行化实现万亿参数模型训练&#xff1a; D…

【算法】使用二分查找解决算法问题:理解二分法思想,模板讲解与例题实践

文章目录 二分算法思想 / 性质 / 朴素模板二分查找的引入&#xff08;二段性&#xff09;704.二分查找 模板34.在排序数组中查找元素的第一个和最后一个位置 二分查找的前提条件 / 时间复杂度分析 算法题69.x的平方根35.搜索插入位置852.山脉数组的峰顶索引162.寻找峰值153.寻找…