### C/C++常见面试题详解
#### 概念问答题
**1. static关键字在C与C++中的含义**
- **C语言中的static**: 在C语言中,`static`主要用于控制变量的可见性和生命周期。
- 当`static`用于变量时,该变量成为静态变量,其生命周期与程序相同,即使在函数退出后仍然保留其值。
- 如果用于函数,则仅在定义该函数的源文件中可见。
- **C++中的static**: 在C++中,`static`的功能与C相似,但也有一些扩展。
- 除了上述功能外,`static`还可以用于类的成员变量和成员函数。
- `static`成员变量在整个类的所有实例之间共享同一份拷贝。
- `static`成员函数同样可以在没有类实例的情况下访问,但只能访问类的`static`成员变量和其他`static`成员函数。
**2. const关键字的理解**
- **C语言中的const**: 在C语言中,`const`用于声明一个只读变量。一旦初始化,该变量的值就不能被更改。
- **C++中的const**: 在C++中,`const`不仅可以用于声明只读变量,还可以用来创建常量对象或常量成员函数。
- 常量对象不允许修改其成员变量。
- 常量成员函数不允许修改其所属对象的状态。
**3. volatile关键字的作用**
- **volatile**通常用于修饰那些可能会被意外修改的变量,例如被硬件设备(如定时器)或并发环境下的其他线程所修改的变量。这告诉编译器不要优化掉这些变量的读写操作,确保每次读取都是从内存中获取最新值。
**4. new/delete与malloc/free的区别**
- **new/delete**是C++特有的操作符,用于动态内存分配和释放。它们与构造函数和析构函数紧密集成,这意味着在分配内存时会自动调用构造函数,释放内存时会调用析构函数。
- **malloc/free**是C标准库中的函数,用于分配和释放内存。它们没有自动调用构造函数或析构函数的能力。
- `new`可以重载,允许自定义内存分配行为。
- `new`失败时会抛出异常,而`malloc`失败时返回`NULL`。
- `new`可以使用`new (placement)`定位符直接放置对象,而`malloc`无法提供这样的功能。
**5. 函数指针、指针数组和数组指针**
- **函数指针**: `int(*ptr)();` 这是一个指向返回`int`类型的函数的指针。
- **指针数组**: `int *ptr[];` 这是一个数组,其中每个元素都是指向`int`类型的指针。
- **数组指针**: `int(*ptr)[];` 这是一个指向数组的指针,数组中的每个元素都是`int`类型。
**6. 指针与数组的区别**
- **指针**是一个存储内存地址的变量。
- **数组**是一组连续的内存位置,用于存储一系列相同类型的数据。
- 数组名实际上是数组首元素的地址。
- 指针可以指向任何地方,包括数组或单独的变量。
- 当数组作为函数参数传递时,实际上传递的是指向数组首元素的指针。
**7. const与#define的不同**
- **const**: 在C++中,`const`可以创建一个常量,类型安全,并且可以参与表达式计算。
- **#define**: 宏定义在预处理阶段替换文本,没有类型安全检查。
**8. 结构体内存对齐**
- **内存对齐**是为了提高数据访问效率而采取的一种措施。
- 大多数处理器要求某些类型的数据位于特定的地址边界上。例如,在32位系统中,`int`类型通常要求4字节对齐。
- 结构体中成员的排列方式会影响到整个结构体的大小,通常会添加填充字段以满足对齐要求。
- 对齐可以通过编译器选项调整。
**9. strlen与sizeof的差异**
- **strlen**: 计算字符串长度,遇到`\0`结束。
- **sizeof**: 返回变量或类型的字节大小,适用于任何类型的数据。
- `sizeof`的结果在编译时确定,可用于计算数组的大小。
- `strlen`的结果在运行时确定,专门用于字符串。
- `sizeof`不执行任何计算操作,而`strlen`可能涉及循环遍历。