今天发现了一个挺奇怪的问题,就是在430的RAM中,想给连续的内存地址分配一个char型和一个int型变量时,两个变量之间的地址会跳一个。具体情况看下图。
从上图可以看到,第一根红线表面一个unsigned char型变量的值为108,地址为0x472A,占一个字节;紧接着下一个为unsigned char型变量,其值为2,地址为0x472C,占两个字节。那0x472B这个地址哪儿去了呢?我们可以看到,在存一个char型变量,后面接一个int型变量时,中间会有一个地址被跳过去;
类似的情况还出现在char型变量后面存一个long int型变量时,但是int型变量和long int型变量连续存,或者单独的char型变量连续存,以及单独的int或long int连续存时,均不存在这个问题。
这个挺奇怪的……这对于SD卡参数的解析会有很大影响。可能是跟编译器有关,这里我用的是CCS V5.4。等找到解决方案之后,再在后文补上。
***********************************************************************************************
获得了问题的答案,很开心~这里与大家分享一下。
出现这个问题的原因是结构体的对齐问题。简单地说,就是char型变量的地址是任意的;但是int型变量由于要占2个字节,为了提高CPU的访问速度,所以其首地址必须要为偶数;long int型占4个字节,其首地址必须要为4的倍数。
关于这个问题再具体的讲解,我摘录了"单片机结构体内存的分配"中的一段话,原文如下:
“什么是字节对齐
一个变量占用 n 个字节,则该变量的起始地址必须能够被 n 整除,即: 存放起始地址 % n = 0, 对于结构体而言,这个 n 取其成员种的数据类型占空间的值最大的那个。
为什么要字节对齐
内存空间是按照字节来划分的,从理论上说对内存空间的访问可以从任何地址开始,但是在实际上不同架构的CPU为了提高访问内存的速度,就规定了对于某些类型的数据只能从特定的起始位置开始访问。这样就决定了各种数据类型只能按照相应的规则在内存空间中存放,而不能一个接一个的顺序排列。
举个例子,比如有些平台访问内存地址都从偶数地址开始,对于一个int型(假设32位系统),如果从偶数地址开始的地方存放,这样一个读周期就可以读出这个int数据,但是如果从奇数地址开始的地址存放,就需要两个读周期,并对两次读出的结果的高低字节进行拼凑才能得到这个int数据,这样明显降低了读取的效率。”
根据这个原理,我利用CCS在MSP430F6638上做了一个简单的测试。
首先定义了两个char型变量和一个int型变量,其内存分配如下如所示。我们可以看到,此时int型变量的首地址为偶数,内存分配是连续的。
然后我只定义一个char型变量和一个int型变量,其内存分配如下图所示,我们可以看到,不连续了。因为int型变量的首地址必须问偶数,所以跳了一个字节。