文章目录
1.C语言的 malloc 和 C++ 中的 new 有什么区别
new 、delete 是操作符,可以重载,只能在C++ 中使用;
malloc、free 是函数,可以覆盖,C、C++ 中都可以使用;
new 可以调用对象的构造函数,对应的delete 调用相应的析构函数;
malloc 仅仅分配内存,free 仅仅回收内存,并不执行构造和析构函数;
new 、delete 返回的是某种数据类型指针,malloc、free 返回的是void 指针;
注 意 : m a l l o c 申 请 的 内 存 空 间 要 用 f r e e 释 放 , 而 n e w 申 请 的 内 存 空 间 要 用 d e l e t e 释 放 , 不 要 混 用 ;
2. 写一个 “标准”宏MIN
#define min(a,b) ((a)<=(b)?(a):(b))
3. 介绍 volatile 及其作用
volatile 影响编译器编译的结果,volatile指出 变量是随时可能发生变化的,与volatile变量有关的运算,不要进行编译优化,以免出错,(VC++ 在产生release版可执行码时会 进行编译优化,加volatile关键字的变量有关的运算,将不进行编译优化)
比如:
volatile int i=10;
int j = i;
...
int k = i;
volatile
告诉编译器i是随时可能发生变化的,每次使用它的时候必须从i
的地址中读取,因而编译器生成的可执行码会重新从i的地址读取数据放在k
中。 而优化做法是,由于编译器 发现两次从i读数据的代码之间的代码没有对i
进行过操作,它会自动把上次读的数据放在k
中。而不是重新从i
里面读。这样以来,如果i是一个寄存器变量或者表示一个端口数据就容 易出错,所以说volatile
可以保证对特殊地址的稳定访问,不会出错;
一个定义为volatile
的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:
-
并行设备的硬件寄存器(如:状态寄存器)
-
一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
-
多线程应用中被几个任务共享的变量 回答不出这个问题的人是不会被雇佣的。
我认为这是区分C程序员和嵌入式系统程序员的最基本的问题。搞嵌入式的家伙们经常同硬件、中断、RTOS等等打交道,所有这些都要求用到volatile变量。不懂得volatile的内容将会带来灾难。假设被面试者正确地回答了这是问题(嗯,怀疑是否会是这样),我将稍微深究一下,看一下这家伙是不是直正懂得volatile完全的重要性。
-
一个参数既可以是const还可以是volatile吗?解释为什么。
-
一个指针可以是volatile 吗?解释为什么。
-
下面的函数有什么错误:
int square(volatile int *ptr)
{
return *ptr * *ptr;
}
下面是答案:
-
是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。
-
是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向buffer的指针时。
-
这段代码有点变态,这段代码的目的是用来返指针ptr指向值的平方,但是,由于ptr指向一个
volatile
型参数,编译器将产生类似下面的代码:
int square(volatile int *ptr)
{
int a,b;
a = *ptr;
b = *ptr;
return a * b;
}
由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。结果,这段代码可能返不是你所期望的平方值!
正确的代码如下:
long square(volatile int *ptr)
{
int a;
a = *ptr;
return a * a;
}
总结volatile
的作用有如下两点:
- 告诉
compiler
不能做任何优化; - 表示用
volatile
定义的变量会在程序外被改变,每次都必须从内存中读取,而不能把他放在cache或寄存器中重复使用;
一般在下列场所使用volatile
:
- 状态寄存器一类的并行设备硬件寄存器。
- 一个中断服务子程序会访问到的非自动变量。
- 多线程间被几个任务共享的变量。
注 意 : 虽 然volatile
在 嵌 入 式 方 面 应 用 比 较 多 , 但 是 在 P C 软 件 的 多 线 程 中 , volatile
修 饰 的 临 界 变 量 也 是 非 常 实 用 的 ;
参考文章:
C语言中volatile的用法及意义
4. 一个参数可以既是const又是volatile吗
这个其实在第三个题已经说了,肯定是可以的,二者目的不同;
可 以 , 用 c o n s t
和 v o l a t i l e
同 时 修 饰 变 量 , 表 示 这 个 变 量 在 程 序 内 部 是 只 读 的 , 不 能 改 变 的 , 只 在 程 序 外 部 条 件 变 化 下 改 变 , 并 且 编 译 器 不 会 优 化 这 个 变 量 。 每 次 使 用 这 个 变 量 时 , 都 要 小 心 地 去 内 存 读 取 这 个 变 量 的 值 , 而 不 是 去 寄 存 器 读 取 它 的 备 份 。注 意 : 在 此 一 定 要 注 意 c o n s t 的 意 思 , const 只 是 不 允 许 程 序 中 的 代 码 改 变 某 一 变 量 , 其 在 编 译 期 发 挥 作 用 , 它 并 没 有 实 际 地 禁 止 某 段 内 存 的 读 写 特 性 。
5. a 和&a 有什么区别
& a : 其 含 义 就 是 “ 变 量 a 的 地 址 ” ,在C++中亦有引用的意思,通过内存地址来操作对象本身,属于引用传递;
*a
: 用 在 不 同 的 地 方 , 含 义 也 不 一 样 。
- 在声明语句中,
*a
只说明a
是一个指针变量,如int *a
; - 在其他语句中,
*a
前面没有操作数且a
是一个指针时,*a
代表指针a
指向的地址内存放的数据,如b=*a
; *a
前面有操作数且a
是一个普通变量时,a
代 表 乘 以a
, 如c = b*a
;