问答题 [说明]
嵌入式C语言编程中常涉及位运算、宏定义的问题,以及大端方式(Big-endian)、小端方式(Little-endian)的访问问题。
问答题 嵌入式系统中常要求用户对变量或寄存器进行位操作。下面的两个函数分别为设置和清除变量a的第5位。请使用下面的宏定义BIT5按要求对变量a进行相应的处理。在函数set_bit5中,用位或赋值操作(|=)设置变量a的第5位,在函数clear_bit5中,用位与赋值操作(&=)清除变量a的第5位。
#define BIT5 (0x01<<5)
static int a;
void set_bit5(void)
{
__①__ ; /*设置变量a的第5位*/
}
void clear_bit5(void)
{
__②__ ; /*清除变量a的第5位*/
}
【正确答案】
【答案解析】①a|=BIT5
②a&=~BIT5 在32位机中,宏BIT5所定义的数值的二进制形式为00000000 00000000 00000000 00100000,~BIT5的二进制形式为11111111 11111111 11111111 11011111。在位运算中,任何值与1进行或操作之后结果都为1,与0进行或操作之后结果还是原数。同样,任何值与0进行与操作之后结果都为0,与1进行与操作之后结果还是原数,所以通过位的或操作可以将一个数值中的某位设置为1,通过与操作方式可以将一个数值中的某位设置为0。a|=BIT5将a的第5位置1,其他位不变,a&=~BIT5将a的第5位置0,其他位不变。
问答题 下图所示代码的设计意图是计算1~100各数的平方。该段代码运行后,没有得到应有的结果,请说明出错原因,将答案填入对应栏内。

下图是在不改变宏定义的情况下,对程序进行修改。请完成该段代码,将答案填入对应栏内。
【正确答案】
【答案解析】出错原因:
在宏定义中,参数a使用两次,而在引用宏时,使用了i++,从而导致出错。
①i
②i++或i=i+1或++i或i+=1 对问题2中的代码进行宏展开之后,计算平方的语句为result=SQUARE((i++)*(i++)),这里使用了两次“i++”表达式,单次循环两次使用i++显然不是该程序的初衷。所以不能得到期望的结果,应该避免两次i++的使用。
问答题 某嵌入式处理器工作在大端方式(Big-endian)下,其中unsigned int为32位,unsigned short为16位,unsigned char为8位。仔细阅读并分析下面的C语言代码,写出其打印输出的结果,将答案填入对应栏内。
#include "stdio.h"
#include "stdlib.h"
void *MEM_ADDR;
void mem_test(void)
{
unsigned int *pint_addr=NULL;
unsigned short *pshort_addr=NULL;
unsigned char *pchar_addr=NULL;
MEM_ADDR=(void *)malloc(sizeof(int));
pint_addr=(unsigned int *)MEM_ADDR;
pshort_addr=(unsigned short *)MEM_ADDR;
pchar_addr=(unsigned char *)MEM_ADDR;
*pint_addr=0x12345678;
printf("0x%x, 0x%x\n", *pshort_addr, *pchar_addr);
/*第一次输出*/
pshort_addr++;
*pshort_addr=0x5555;
printf("0x%x, 0x%x\n", *pint_addr, *pchar_addr);
/*第二次输出*/
pchar_addr++;
*pchar_addr=0xAA;
printf("0x%x, 0x%x\n", *pint_addr, *pshort_addr);
/*第三次输出*/
}
【正确答案】
【答案解析】第一次输出:0x1234,0x12
第二次输出:0x12345555,0x12
第三次输出:0x12aa5555,0x5555 在计算机中,数据是以字节为单位进行存储的。以整型数据0x12345678为例,在小端模式计算机中(x86),该数据分成4个字节依次存储在连续的4个字节的地址空间中,从低到高依次为0x78、0x56、0x34、0x12;而在大端模式系统中(PPC通常设置为大端模式),该数据从低地址空间到高地址空间的存储顺序为0x12、0x34、0x56、0x78,根据这种存储方式,可以得出题目中的多种内存访问方式的访问位置及内容。