嵌入式指针及相关概念

嵌入式指针及相关概念

  • 尾端 (Endianness)

尾端由Danny Cohen(Cohen 1980)由一篇论文引入计算机界,作者注意到计算机体系结构基于字节寻址和整数定义在通信系统中的不同定义分为“大尾端”(Big-endian)和“小尾端”(Little-endian)两个阵营。一个十六进制整形数据0x12345678传递给另外一个采用不同尾端的计算机系统时可能会被理解为0x78563412甚至0x1E6A2C48。这就是尾端命题。尾端直接决定着数据在存储器内的组织形式。

  • 地址空间 (Address Space)

存储器中,由存储单元地址或集合所构成的集合称为地址空间。

  • 线性地址空间 (Linear Address Space)

如果一个地址空间中所有的元素可以组成一个由整数构成的唯一闭区间,则称该地址空间为线性地址空间。

  • 扁平地址空间 (Flat Address Space)

一个地址空间可以由多个不同纬度的线性地址空间构成,当地址空间中只有唯一的一个线性地址空间时,或者地址空间中不同的线性地址空间可以被影射到同一个彼此不相交的纬度时,则称该地址空间为扁平地址空间。

  • 内存组织方式

除去字节、字符、字符串和字节流,C语言中几乎所有的数据类型,准确说是这些数据类型在存储器内部的组织方式都要受到尾端的影响。出于历史的原因,IBM及其兼容的计算机系统采用大尾端系统,习惯上又被称为大端对齐系统;DEC和Intel及其兼容的计算机系统采用小尾端系统,习惯上又称为小端对齐系统。
只有在进行字节寻址时才会有尾端的问题。早期计算机工程师在20世纪60年代晚期都是对单字节进行操作:指令、整型和内存宽度都是相同的字宽度。这样的计算机系统不存在尾端的概念,只有字在内存中的顺序、以及字内部二进制位序的问题。
我们在书写十进制数字式,都是先写高位再写低位;对数据的读取也采用同样的方式。为了符合这一习惯,IBM的工程师们尝试寻找一种以字为单位的数值表示方法。当我们按照习惯将内存单元按照从左到右地址增加的顺序依次排列开来,可以发现字的数值是直接可读的,或者说字的表示形式符合人们从左至右、从高位开始读取数字的习惯。(如图12.1所示)此时,由于存储器从左到右地址是依次递增的,字节内二进制位序从左到右也是依次递增的关系,因而在一个字内,二进制位序实际上与数值的位序正好相反。这就是大尾端的形成原因。
另一方面,我们也习惯于很自然的给每一个字节的二进制位赋予一个权值,比如BIT0的权值为1、BIT1的权值为2、BIT2为4……BIT7为128,这实际上就是将字节的二进制位序作为该位权值以2位底的幂指数,简单的说,BITn的权值就等于2n。用这种顺序可以非常自然的由多个字节组成较大的数据类型,这就是小尾端形成的原因。

  • 硬件与尾端

在物理上,大尾端以字为单位组织数据(如图12.1大尾端图示的粗横线所示),字内的位序与实际的物理位序完全相反。大尾端认为,在字内第一字节物理位0为最高位(MSB,Most Significant Bit);第四字节物理位7为最低位(LSB,Least Significant Bit)。小尾端以字节为单位组织数据,数据元素的字节序与存储器的字节序相同,字节内部的位序也与物理位序相同:物理位0为最低位LSB、物理位7位最高位MSB。
对比图12.1中两种尾端对十六进制数字0x12345678的组织形式很容易发现:当我们把存储器按照从左到右地址依次增加的顺序排列开来的时候,小尾端系统读取到的数据依次为0x78、0x56、0x34和0x12;大尾端读取到的数据依次为0x12、0x34、0x56和0x78,符合人们的阅读习惯。在大尾端系统中,数据的组织必须以字为单位,否则因为逻辑位序与物理位序的冲突而导致数据的混乱。在大尾端系统中,CPU内核与存储器往往都是按照大尾端形式组织数据的;在小尾端系统中,CPU与存储器往往都是按照小尾端形式组织数据的;外设与总线的尾端往往可以根据不同的设计需求而有所不同。

存储器大尾端和小尾端结构示意图(表示十六进制数字0x12345678)

  • 存储器对齐方式

很多计算机系统为了寻址的便利,或者由于数据操作类型的限制(例如,AVR32每次只能以32位数据为单位进行读写操作)要求用户将数据或变量尽可能的对齐到指定的地址上。32位计算机往往要求用户将数据对齐到字(WORD,4Byte)或者半字(Half WORD,2Byte),AVR作为8位微处理器,以字节为单位进行寻址,因而对用户没有数据对齐的要求。使用C语言进行软件开发时,编译器会自动对用户声明的变量按照处理器的要求进行对齐,例如,针对下面的全局变量声明,字对齐模式下的内存示意如图所示;半字对齐模式下的内存示意如图所示;字节对齐模式下的内存示意如图所示:

1 /* 使用C99标准数据类型 */
2 #include <stdint.h>
3 /* 全局变量声明 */
4 uint8_t a;
5 uint16_t b;
6 uint32_t c;

posted on 2012-09-18 14:24 竞击 阅读( ...) 评论( ...) 编辑 收藏
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
嵌入式C语言中,指针是一个非常重要的概念。它允许我们直接访问内存中的数据,并有效地操作和传递数据。以下是一些嵌入式C语言指针的常见用法: 1. 变量地址获取:可以使用指针获取变量在内存中的地址,通过在变量名前加上 '&' 符号来获取。例如,如果有一个整数变量 x,可以使用 int *ptr = &x; 来获取 x 的地址,并将其存储在指针变量 ptr 中。 2. 间接访问:通过指针,可以间接地访问和修改变量的值。例如,如果有一个指针变量 ptr 指向一个整数变量 x,可以使用 *ptr 来访问和修改 x 的值。例如,*ptr = 10; 将会把 x 的值修改为 10。 3. 动态内存分配:在嵌入式系统中,内存资源通常是有限的。使用指针,我们可以在运行时动态地分配和释放内存。通过使用函数如 malloc() 和 free(),可以分配和释放堆内存。例如,int *ptr = (int *)malloc(sizeof(int)); 可以动态地分配一个整数大小的内存块,并将其地址存储在指针变量 ptr 中。 4. 数组访问:指针也可以用于访问数组元素。数组名本身就是一个指向数组首元素的指针。可以通过指针进行数组元素的访问和操作。例如,int arr[5]; int *ptr = arr; 可以将数组 arr 的首地址存储在指针变量 ptr 中,并通过指针操作数组元素。 5. 函数指针:在嵌入式系统中,函数指针是一种常见的用法。通过函数指针,可以动态地调用不同的函数。例如,定义一个函数指针变量 int (*funcPtr)(int, int); ,然后将其指向不同的函数,可以在运行时决定调用哪个函数。 这些只是嵌入式C语言指针的一些常见用法,它们在嵌入式系统开发中非常重要。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值