c语言面试知识汇总(2)
1. Volatile
Volatile 定义的变量,直接读取内存,寄存器中的内容,实时改变
下面是我在书上看到的一个通俗易懂的写法
2. 嵌入式系统总是要用户对变量或寄存器进行位操作。给定一个整型变量a,写两段代码,第一个设置a的bit 3,第二个清除a 的bit 3。在以上两个操作中,要保持其它位不变。
#define BIT3 (0x1<<3) //将1左移3位
static int a;
void set_bit3(void)
{
a |= BIT3; // a 或上 BIT3,只改变一位
}
void clear_bit3(void)
{
a &= ~BIT3; // ~BIT3第三位是0其余为1 ,在与上a 保证 第三位是0,其余位是不变
}
3.中断是嵌入式系统中重要的组成部分,这导致了很多编译开发商提供一种扩展—让标准C支 持中断。具代表事实是,产生了一个新的关键字 __interrupt。下面的代码就使用了__interrupt关键字去定义了一个中断服务子程序(ISR),请评论一下这段代码的。
__interrupt double compute_area (double radius)
{
double area = PI * radius * radius;
printf(" Area = %f", area);
return area;
}
4. 整数自然转换原则
A. 若参与的类型不同,则先转换成同一类型,然后运算;(从低->高)
B . 所有的浮点运算都是以双精度进行的,即使仅含float单精度运算的表达式,也先转换才double类型,再作运算;
C. char类型和short类型参与运算时,必须先转换成int类型;
D. 在赋值运算中,无论赋值符右侧的类型如何,都将转换成左侧变量的类型。
5. 若 尽管不像非嵌入式计算机那么常见,嵌入式系统还是有从堆(heap) 中动态分配内存的过程的。那么嵌入式系统中,动态分配内存可能发生的问题是什么?右侧数据精度具有较高等级,则将被截短或舍入,使结果与左侧变量的类型相同。
- malloc/free是c/c++标准库 new/delete是c++运算符 相比较来说new 分配内存要好一点,new在分配内存时,计算空间大小和初始化,malloc没有,其他过程都差不多。
- 动态分配可能会发生的问题:
- 碎片收集(vb,jave,c#):c/c++没有垃圾收集器
- 内存碎片:动态分配时,要分配内存大小大于堆上连续可分配的的内存大小,而堆上连续可分配的大小就是称为内存碎片。
- 内存泄漏:分配内存,忘记释放
有趣的讲了垃圾收集器:https://blog.****.net/erazy0/article/details/5470222
6. Typedef的用法
-
- 定义一种类型的别名,而不只是简单的宏替换。可以用作同时声明指针型的多个对象。
- typedef与结构体结合
Typedef student p{
...
}q;
进行了两个操作:
定义了一个新的结构体。Strut p;
给结构体取的名字是q;
3. 用typedef来定义与平台无关的类型。
4. 为复杂的声明定义一个新的简单的别名。
具体分析:http://www.cnblogs.com/csyisong/archive/2009/01/09/1372363.html
7. a++和++a能不能左值
1)首先说左值和右值的定义:
变量和文字常量都有存储区,并且有相关的类型。区别在于变量是可寻址的(addressable)对于每一个变量都有两个值与 其 相 联:
它的数据值,存储在某个内存地址中。有时这个值也被称为对象的右值(rvalue,读做are-value).我们也可认为右值的意思是被读取的值(read value)。文字常量和变量都可被用作右值。
它的地址值——即存储数据值的那块内存的地址。它有时被称为变量的左值(lvalue,读作ell-value)。我们也可认为左值的意思是位置值,文字常量不能被用作左值。
a++的意思是先复制一份临时数据出来参与周边环境的运算,再自加变量a,可见a++用来参与运算的是一份复制出来的临时数据,这个数据是临时存在而没有固定地址的,不是一个真正的变量。
++a的意思是先自加变量a,再将变量放到周边环境参与运算,那么++a用来参与运算的是有具体地址的变量,所以++a是可以作为左值使用的。