文章目录
- 1、 用 预处理指令 #define 声明一个常数,用以表明 1 年中有多少秒(忽略闰年问题)
- 2、 写一个标准宏 MIN ,这个宏输入两个参数,并返回较小的一个
- 3、 预处理器标识 #error 的目的是什么
- 4、 嵌入式系统中经常要用到无限循环,你怎么样用 C 编写死循环
- 5、 用 变量 a 给出下面的定义
- 6、static 的作用,请写出两个;
- 7、关键字`const`的作用;
- 8、`volatile`的作用;
- 9、 嵌入式系统总是要用户对变量或寄存器,进行`位操作`;
- 10、嵌入式系统经常具有要求程序员去访问某`特定的内存位置`,要求设置一绝对地址为`0x67a9`的整型变量的值为`0xaa66`;
- 11、中断的概念
- 12、代码输出结果;
- 13、 评价下面的代码片断:
- 14、 动态内存分配;
- 15、`typedef`语句用于给基本数据类型和导出数据类型定义一个新的名字
- 16、分析代码
1、 用 预处理指令 #define 声明一个常数,用以表明 1 年中有多少秒(忽略闰年问题)
#define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL
2、 写一个标准宏 MIN ,这个宏输入两个参数,并返回较小的一个
#define MIN(A,B) ((A) <= (B) ? (A):(B))
3、 预处理器标识 #error 的目的是什么
#error : 停止编译 并显示 错误信息
4、 嵌入式系统中经常要用到无限循环,你怎么样用 C 编写死循环
while(1){...}
do {...} while(1)
for(;;){...}
5、 用 变量 a 给出下面的定义
序号 | 定义 | 效果 |
---|---|---|
1 | int a | 整型 数 |
2 | int * a | 指向整型数 的指针 |
3 | int ** a | 指向指针 的指针 ,它指向 的指针 指向整型数 |
4 | int a[10] | 有10个整型数 的数组 |
5 | int * a[10] | 有10个指针 的数组 ,它的指针 指向整型数 |
6 | int (*a)[10] | 指向 有10个整型数 的数组 的指针 |
7 | int (*a)(int) | 指向函数 的指针 ,该函数 有一个整型参数 ,并返回一个整型数 |
8 | int (*a[10])(int) | 有10个指针 的数组 ,该指针 指向一个函数 ,该函数 有一个整型参数 并返回一个整型数 |
6、static 的作用,请写出两个;
序号 | 作用 |
---|---|
1 | 函数体 内static 变量 的作用范围为该函数体 ,该变量的内存只被分配一次 ,因此其值在下次调用时仍维持上次的值 |
2 | 模块 内的static 全局变量 可以被模块 内所有函数访问 ,但不能被模块外 其他函数 访问 |
3 | 模块 内的static 函数 ,只可被这一模块内的其他函数调用 ,这个函数的使用范围 被限制在声明它 的模块内 |
7、关键字const
的作用;
序号 | 作用 |
---|---|
1 | 只读 |
2 | 使用关键字const 也许能产生更紧凑的代码 |
3 | 使编译器 很自然地保护 那些不希望被改变的参数 ,防止其被无意的代码修改 |
另外使用const
定义变量:
序号 | 定义 | 效果 |
---|---|---|
1 | const int a | a 是常 整型数 |
2 | int const a | a 是常 整型数 (同上) |
3 | const int * a | a 是 指向常 整型数 的指针 (const 修饰int ,所以是常 整型数 ) |
4 | int * const a | a 是 指向整型数 的常指针 (const 修饰a ,所以a 是常指针 ) |
5 | const int * const a | a 是 指向常 整型数 的常指针 |
8、volatile
的作用;
定义为volatile
的变量可能会被意想不到地改变,优化器
在用到这个变量
时必须重新读取
这个变量的值
,而不是保存在寄存器
里的备份
。
volatile变量的例子:
序号 | 作用 |
---|---|
1 | 并行设备的硬件寄存器(如状态寄存器) |
2 | 一个中断服务子程序中会访问到的非自动变量 |
3 | 多线程应用中,被几个任务共享的变量 |
9、 嵌入式系统总是要用户对变量或寄存器,进行位操作
;
#define BIT3 (0x01 << 3)
static int a;
void set_bit3()
{
a |= BIT3; //置 1
}
void clear_bit3()
{
a &= ~BIT3; //清 0
}
10、嵌入式系统经常具有要求程序员去访问某特定的内存位置
,要求设置一绝对地址为0x67a9
的整型变量的值为0xaa66
;
int * ptr = NULL;
ptr = (int *) 0x67a9;
*ptr = 0xaa66;
11、中断的概念
当某个事件发生时,CPU 停止运行正在执行的程序,而转去执行处理该事件的程序,处理该事件后,返回原程序继续执行下去的过程;
ISR
:中断服务程序
(Interrupt Service Routines
)
序号 | 作用 |
---|---|
1 | ISR 不能返回值 |
2 | ISR 不能传递参数 |
3 | ISR 应该是短而有效率 的,在ISR 中做浮点运算 是不明智的 |
4 | printf() 经常有重入和性能上的问题,所以不能在中断处理函数里调用printf() |
12、代码输出结果;
void foo(void)
{
unsigned int a = 6;
int b = -20;
(a + b > 6) ? puts(" > 6 ") : puts(" <= 6 ");
}
当表达式 中存在 有符号
类型 和 无符号
类型 时,所有的 操作数 都自动转换为 无符号
类型,因此 -20 变成了一个非常大的正整数,该表达式计算出的结果 大于6,答案是输出 > 6。
13、 评价下面的代码片断:
unsigned int zero = 0;
unsigned int comp_zero = 0xFFFF; //0 的反码(错误结果)
对于一个int
型不是16位的处理器
来说,上面的代码是不正确的
。
正确结果编写如下:
unsigned int comp_zero = ~0; //0 的反码(正确结果)(complement 反码)
14、 动态内存分配;
int * p = NULL;
p = (int *) malloc(sizeof(int) * 128); //内存申请
free(p); //内存释放
15、typedef
语句用于给基本数据类型和导出数据类型定义一个新的名字
#define dPS struct s *
typedef struct s * tPS;
dPS p1 , p2; //错误定义,实际结果是 struct s * p1, p2;
tPS p3 , p4; //正确定义了两个指针
16、分析代码
int a = 5, b = 7, c;
c = a +++ b;
上面的代码被处理成:c
= a++
+ b
;代码执行后 a = 6
, b = 7
, c = 12
。