C常见面试问题
- “零”值比较
bool flag;
if (flag) {}
int flag;
if (0 == flag) {}
float flag;
const float EPSINON = 0.000001;
if (flag >= -EPSINON && flag <= EPSINON) {}
- sizeof 和 strlen 区别
- sizeof 是操作符,strlen 是库函数;
- sizeof 参数可以是变量类型,也可以是变量, strlen 参数只能是以'\0'结尾的字符串;
- sizeof 在编译时执行,strlen 是在运行时执行;
- sizeof 计算的是数据类型占用的内存大小,strlen 返回的是字符串的实际长度;
- sizeof 参数为指针时不会退化, strlen 会退化为指针。
- C malloc和C++ new的区别
- malloc和free对应,new和delete;
- malloc是库函数,new是操作符,可以进行重载;
- malloc仅仅申请内存,new会执行对象的构造函数;
- malloc返回void*指针,new返回对象类型指针。
- volatile 作用
作为指令关键字,volatile确保本条指令不会被编译器优化而省略,且要求每次从直接读取。
一个被定义为volatile的变量说明这个变量可能被意想不到的改变,编译器不应该随便假设这个变量的值,使用这个变量的时候都必须重新读区,而不是使用寄存器中的备份。
应用场景:
- 并行设备的硬件寄存器,如:状态寄存器;
- 中断子程序中会访问的非自动变量;
- 多线程中共享的变量。
- 变量定义
- 一个整型数:
int a;
- 一个指向整型的指针:
int *a;
- 一个指向指针的指针,它的指针指向一个整型:
int **a;
- 一个整型数组:
int a[10];
- 一个整型指针数组:
int *a[10];
- 一个指向整型数组的指针:
int (*a) [10];
- 一个指向函数的指针,该函数有一个整型参数并返回整型数:
int (*a) (int);
- 一个指针数组,该数组的指针指向一个函数,该函数有一个整型参数并返回一个整型数:
int (*a[10]) (int);
- 引用和指针的区别
- 指针是一个实体,引用是别名;
- 引用使用时不需要解引用,指针需要(*);
- 引用在定义的时候进行初始化一次,之后不可改变,指针可以改变指向;
- 引用没有const,指针有const,const指针不可改变;
- 引用不能为空,指针可以;
- sizeof返回引用指向的变量大小,sizeof指针得到的是指针本身的大小;
- 指针自增操作改变指向的位置,引用自增是对指向的变量自增。
- static用法
- static 定义局部变量,变量存放在静态数据区,在编译时分配内存空间,如何没有明确初始化,默认为0,运行时该变量在函数退出后不会释放;
- static 定义全局变量,该变量只在文件内部可见,不能被外部引用;
- static 修饰函数,该函数只在文件内部可见。
- #define和typedef
- #define宏定义是字符替换,typedef是定义一种新的类型;
- #define是在预处理的时候进行替换,编译阶段是处理宏处理后的代码,typedef定义的新类型是编译阶段的一部分;
- 可重入函数和不可重入函数
可重入函数:可以被多个任务或者线程共享的函数。这些函数在任何时候可以被打断,然后再次调用,而不会丢失数据。可重入函数不依赖于全局或者静态变量,只依赖参数和局部变量,因此,它们在多任务或者多线程环境是安全的。
不可重入函数:不可以被多个任务或者线程共享的函数。这些函数可能会使用全局变量或者静态变量,或者其他共享的资源,如文件、输入输出设备等。如何一个不可重入的函数被打断,并由另外的任务或者线程再次调用,可能导致数据的混乱,产生不可预期的结果。
- 内存布局
CSDN 内存布局