白培中最新消息现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特 定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。
对齐的作用和原因:各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取。比如有些架构的CPU在访问 一个没有进行对齐的变量的时候会发生错误,那么在这种架构下编程必须保证字节对齐。其他平台可能没有这种情况,但是最常见的是如果不按照适合其平台要求对 数据存放进行对齐,会在存取效率上带来损失。比如有些平台每次读都是从偶地址开始,如果一个int型(假设为32位系统)如果存放在偶地址开始的地方,那 么一个读周期就可以读出这32bit,而如果存放在奇地址开始的地方,就需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该32bit数 据。显然在读取效率上下降很多。
结构体A中包含了4字节长度的int一个,1字节长度的char一个和2字节长度的short型数据一个,B也一样;按理说A,B大小应该都是7字节。
之所以出现上面的结果是因为编译器要对数据成员在空间上进行对齐。上面是按照编译器的默认设置进行对齐的结果,那么我们是不是可以改变编译器的这种默认对齐设置呢,当然可以。例如:
对于char型数据,其自身对齐值为1,对于short型为2,对于int,float,double类型,其自身对齐值为4,单位字节。
4.数据成员、结构体和类的有效对齐值:自身对齐值和指定对齐值中小的那个值。
有 了这些值,我们就可以很方便的来讨论具体数据结构的成员和其自身的对齐方式。有效对齐值N是最终用来决定数据存放地址方式的值,最重要。有效对齐N,就是 表示“对齐在N上”,也就是说该数据的“存放起始地址%N=0”。而数据结构中的数据变量都是按定义的先后顺序来排放的。第一个数据变量的起始地址就是数 据结构的起始地址。结构体的成员变量要对齐排放,结构体本身也要根据自身的有效对齐值圆整(就是结构体成员变量占用总长度需要是对结构体有效对齐值的整数 倍,结合下面例子理解)。这样就不能理解上面的几个例子的值了。
假 设B从地址空间0x0000开始排放。该例子中没有定义指定对齐值,在笔者环境下,该值默认为4。第一个成员变量b的自身对齐值是1,比指定或者默认指定 对齐值4小,所以其有效对齐值为1,所以其存放地址0x0000符合0x0000%1=0.第二个成员变量a,其自身对齐值为4,所以有效对齐值也为4, 所以只能存放在起始地址为0x0004到0x0007这四个连续的字节空间中,复核0x0004%4=0,且紧靠第一个变量。第三个变量c,自身对齐值为 2,所以有效对齐值也是2,可以存放在0x0008到0x0009这两个字节空间中,符合0x0008%2=0。所以从0x0000到0x0009存放的 都是B内容。再看数据结构B的自身对齐值为其变量中最大对齐值(这里是b)所以就是4,所以结构体的有效对齐值也是4。根据结构体圆整的要求, 0x0009到0x0000=10字节,(10+2)%4=0。所以0x0000A到0x000B也为结构体B所占用。故B从0x0000到0x000B 共有12个字节,sizeof(struct B)=12;其实如果就这一个就来说它已将满足字节对齐了, 因为它的起始地址是0,因此肯定是对齐的,之所以在后面补充2个字节,是因为编译器为了实现结构数组的存取效率,试想如果我们定义了一个结构B的数组,那 么第一个结构起始地址是0没有问题,但是第二个结构呢?按照数组的定义,数组中所有元素都是紧挨着的,如果我们不把结构的大小补充为4的整数倍,那么下一 个结构的起始地址将是0x0000A,这显然不能满足结构的地址对齐了,因此我们要把结构补充成有效对齐大小的整数倍。其实诸如:对于char型数据,其 自身对齐值为1,对于short型为2,对于int,float,double类型,其自身对齐值为4,这些已有类型的自身对齐值也是基于数组考虑的,只 是因为这些类型的长度已知了,所以他们的自身对齐值也就已知了。
第 一个变量b的自身对齐值为1,指定对齐值为2,所以,其有效对齐值为1,假设C从0x0000开始,那么b存放在0x0000,符合0x0000%1= 0;第二个变量,自身对齐值为4,指定对齐值为2,所以有效对齐值为2,所以顺序存放在0x0002、0x0003、0x0004、0x0005四个连续 字节中,符合0x0002%2=0。第三个变量c的自身对齐值为2,所以有效对齐值为2,顺序存放
如果在编程的时候要考虑节约空间的话,那么我们只需要假定结构的首地址是0,然后各个变量按照上面的原则进行排列即可,基本的原则就是把结构中的变量按照 类型大小从小到大声明,尽量减少中间的填补空间。还有一种就是为了以空间换取时间的效率,我们显示的进行填补空间进行对齐,比如:有一种使用空间换时间做 法是显式的插入reserved成员:
reserved成员对我们的程序没有什么意义,它只是起到填补空间以达到字节对齐的目的,当然即使不加这个成员通常编译器也会给我们自动填补对齐,我们自己加上它只是起到显式的提醒作用。
最后两句代码,从奇数边界去访问unsignedshort型变量,显然不符合对齐的规定。
在x86上,类似的操作只会影响效率,但是在MIPS或者sparc上,可能就是一个error,因为它们要求必须字节对齐。
3. 如果支持看设置了对齐与否,如果没有则看访问时需要加某些特殊的修饰来标志其特殊访问操作。
关键字:编辑:什么鱼 引用地址:基于C51程序设计中字节对齐对程序的影响
当电机较大时,启动是个必须注意的问题。比较简单且用的很多的是星三角启动,这里写出了星三角启动的核心部分。每一个IO口接上继电器,再控制交流接触器,就OK了。但,要注意,星、角交流接触器一定要互锁,否则一旦某个交流接触器粘连,就造成短路了。 #include reg51.h sbit K1=P3^1; //按键1,控制第1个继电器启动 sbit K2=P3^2; //按键2,控制第2个继电器启动 sbit J1=P1^5; //星接继电器 sbit J2=P1^6; //星点继电器 sbit J3=P1^7; //角继电器 void Delay_1ms(unsigned int t) { unsigned int x, y;
前言:软件延时真的很坑,校园网真的很烂 直接上码 LCD1602部分 (1).LCD1602.C #include reg52.h #include LCD1602.h #include INTRINS.h sbit LCD_RS=P2^6; sbit LCD_RW=P2^5; sbit LCD_E=P2^7; #define LCD_DatrPort P0 //指令函数 void LCD_WeitrCommand(unsigned char Command) { LCD_RS=0;//0写指令,1写数据 LCD_RW=0;//write mode LCD_DatrPort=Command; LCD_E
(DHT11)温湿度+LCD1602 /
摘要:通过对鼠标底层通信原理及协议的深入分析,探讨了鼠标在80C196单片机系统中的应用价值与可行性,并介绍了鼠标接口软件设计的原理及方法,给出了80C196单片机与Microsoft鼠标的具体接口程序。 关键词:鼠标 接口技术 软件设计 接口程序 80C196单片机由于低格低、处理能力强,在信号分析、数据采集等很多领域得到了广泛应用,在目标系统中使用各种规格的液晶或CRT显示器也越来越多。因此在这样的单片机系统中引入鼠标,将会方便操作,提高工作效率。鼠标内核本质上是一个二维的角度或位移信号检测装置,耗电极少、可靠性高、价格低廉,可能在许多场合发挥作用。鼠标与主机之间通过RS-232标准串行接口进行通信,信息传送是单方向、无条
型号:LCD12864a3 驱动器:ST7920A 汉字显示坐标图: 图形显示坐标图: /*==================== lcd12864.h =====================*/ #ifndef _LCD12864_h_ #define _LCD12864_h_ #include Atmel/AT89X51.h #include delay.h #include link.h /*================= ST7920LCD 定义 ===================*/ sbit lcd_rs=P2^6; sbit lc
代码]LCD12864头文件[上下屏] /
我们知道C51的指令存储在ROM中,它需要从ROM中取出指令才能知道该干什么事。一条指令,首先应该告诉计算机要做什么性质的操作,是加减,还是跳转判断等;其次,还需要给出拿去运算的数据,可以是直接的数据(就是立即能用的数,立即数),也可以是数据存放的地址。那么如何告诉计算机我这个操作码后面跟的是立即数还是地址呢?简单,做个记号,用#来表示立即数,没记号的都是地址。取出指令时,要放在指令寄存器IR里,送到指令译码器ID里进行译码,随后生成相应的控制命令C,这一点是自然而然的,因为计算机本身是要通过硬件执行的,一个指令代码要译码过后才能被解读。不然直接给CPU一个10001000它根本不知道该干什么,通过译码,可能也是生成一些10001
摘要: 介绍ISO7816-4及中国金融集成电路(IC)卡规范所规定的T=0协议的CPU卡与终端之间的接口特性和传输协议,及以C51语言设计的CPU卡复位、下电及读写程序。 关键词: IC卡 CPU卡 终端 复位 字符传输协议(T=0协议) IC卡的概念是20世纪70年代提出的。法国BULL公司首创IC卡产品,并将这项技术应用到金融、交通、医疗、身份证明等多个方面。IC卡的核心是集成电路芯片,一般为3 μm 以下的半导体技术制造。IC卡具有写入数据和存储数据的能力。IC可存储其中的内容,根据需要可以有条件地供外部读取,或供内部信息处理或校验用。 根据各种集成电路的不同,
#include reg52.h void delay(unsigned char n) //约n(ms)延时 { unsigned char i,j,k; for(k=0;k n;k++) { for(j=0;j 5;j++) // 约1ms延时 { for(i=0;i 31;i++) //约0.1ms延时 {;} } } } main() { while(1) { delay(15); } } /*约15ms延时 ,需较准确延时: 1、在 keil uv
一。什么是字节对齐,为什么要对齐? 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特 定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。 对齐的作用和原因:各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取。比如有些架构的CPU在访问 一个没有进行对齐的变量的时候会发生错误,那么在这种架构下编程必须保证字节对齐。其他平台可能没有这种情况,但是最常见的是如果不按照适合其平台要求对 数据存放进行对齐,会在存取效率上带来损失。比如有些
对程序的影响 /
编程一站式学习
有奖直播报名|Keysight World Tech Day 2023分论坛——汽车自动驾驶与新能源
【下载】LAT1289 Keil、IAR、CubeIDE中变量不被初始化方法
【下载】LAT1288 STM32 G474中Triggered-half模式的实现
【下载】LAT1309 一步一步创建STM32WBA BLE_Custom工程
【课程】STM32 & X-Cube-TouchGFX GUI开发实践
【直播】STM32H5系列:强大的ARM® CORTEX®-M33 MCU让高性能和安全性唾手可得
【直播】STM32U5系列扩充新成员-探索更安全,更高效,更节能的设计
【新品】STM32H5-Arm® Cortex®-M33 内核,主频高达250MHz,提升性能与信息安全性
【新品】STM32MP13X-支持Linux、RTOS和Bare Metal应用,新一代通用工业级MPU
【新品】Arm® Cortex®-M33处理器内核,运行频率160 MHz,基于Armv8-M架构并带有TrustZone®
STM32Cube.AI开发者云:只需四个步骤,轻松将AI集成到MCU
综合资讯51单片机PIC单片机AVR单片机ARM单片机嵌入式系统汽车电子消费电子数据处理视频教程电子百科其他技术STM32MSP430单片机资源下载单片机习题与教程
|