一、C语言
1.const的作用有哪些,谈一谈你对const的理解?
- 声明常量:使用 const 关键字可以声明常量,即一旦赋值后就不能再修改的变量。
2.描述char*、const char*、char* const、const char* const的区别?
- char*:这是一个指向字符的指针,指向的字符可以被修改。例如:
char arr[] = "Hello";
char* str = arr;
str[0] = 'J';// 合法,可以修改指向的字符内容
- const char*:这是一个指向字符的常量指针,指针本身可以被修改,但指向的字符内容不能被修改。例如:
const char* str = "Hello";
str = "World"; // 合法,可以修改指针指向的位置
str[0] = 'J'; // 不合法,不能修改指向的字符内容
- char *const:这是一个指向字符的指针常量,指向的字符内容可以被修改,但指针本身不能被修改。例如:
char arr[] = "Hello";
char* const str = arr;
str[0] = 'J'; // 合法,可以修改指向的字符内容
ptr = "World"; // 不合法,不能修改指针的指向
- const char* const:这是一个指向字符的常量指针常量,既不能修改指针本身,也不能修改指向的字符内容。例如:
const char arr[] = "Hello";
const char* const str = arr;
str[0] = 'J'; // 不合法,不能修改指向的字符内容
str = "World"; // 不合法,不能修改指针的指向
3.指针常量 char *const和常量指针const char*有什么区别?
- 同上char *const 与const char*的比较。
4.static的作用是什么,什么情况下用到static?
- 静态变量:
static可以用来声明静态变量,即在函数内部或在类的成员中声明的变量。静态变量在整个程序的生命周期内都存在,而不是在其声明所在的作用域内存在。例如:
void foo() {
static int count = 0; // 静态局部变量
count++;
}
class MyClass {
public:
static int num; // 静态成员变量声明
};
int MyClass::num = 0; // 静态成员变量定义并初始化
- 静态函数:在类中,
static可以用来声明静态成员函数。静态成员函数不依赖于任何特定的对象实例,可以直接通过类名来调用。例如:
class MyClass {
public:
static void myStaticFunction() {
// 静态成员函数体
}
};
MyClass::myStaticFunction(); // 调用静态成员函数
- 文件作用域:在全局变量和函数之前使用
static关键字,可以使其具有文件作用域,即只能在当前文件中访问,而不能被其他文件访问。例如:
// 文件1.cpp
static int globalVar = 10; // 具有文件作用域
// 文件2.cpp
extern int globalVar; // 无法访问文件1.cpp中的globalVar
5.全局变量与局部变量的区别?
1.作用域:
- 全局变量的作用域是整个程序,从定义处开始直到文件结束,在整个程序中都可以访问。
- 局部变量的作用域限定在声明它的代码块内,在该代码块内部可以访问。
2.生存周期:
- 全局变量在程序启动时创建,在程序结束时销毁,其生命周期与程序运行周期一致。
- 局部变量在声明所在的代码块开始时创建,在代码块结束时销毁,其生命周期只在代码块内
3.内存分配:
- 全局变量通常存储在静态存储区(静态数据区)中,编译时分配内存,直到程序结束才释放。
局部变量通常存储在栈上,动态分配内存,随着函数的调用和返回而动态地分配和释放。
4.访问权限:
- 全局变量可以被程序中的所有函数访问,包括在函数外部和其他文件中。
- 局部变量只能在其声明所在的函数或代码块内部访问,无法被函数外部和其他函数访问。
5.初始化:
- 全局变量可以显式初始化,如果不显式初始化,将被默认初始化为 0 或空指针等。
- 局部变量在定义时可以被初始化,也可以不初始化,未初始化的局部变量将具有未定义的值。
6.宏定义的作用是什么?
- 宏定义(Macro Definition)是C和C++中一种预处理指令,它的作用是在编译之前用指定的文本替换程序中出现的宏名称,以便在编译时实现代码的自动化生成和替换。例如,以下是一个简单的宏定义示例:
#define MAX(a, b) ((a) > (b) ? (a) : (b))
int x = 10, y = 20;
int max_val = MAX(x, y); // 实际替换为 ((x) > (y) ? (x) : (y))
7.内存对齐的概念?为什么会有内存对齐?
- 现代计算机中内存空间都是按照字节(byte)进行划分的,所以从理论上讲对于任何类型的变量访问都可以从任意地址开始,但是在实际情况中,在访问特定类型变量的时候经常在特定的内存地址访问,所以这就需要把各种类型数据按照一定的规则在空间上排列,而不是按照顺序一个接一个的排放,这种就称为内存对齐,内存对齐是指首地址对齐,而不是说每个变量大小对齐。其实是一种空间换时间的操作。
- 内存对齐的主要原因包括:
- 提高内存访问效率:许多处理器要求数据在内存中的地址与其数据类型的大小相对应。如果变量没有按照对齐要求对齐,可能导致处理器需要多次访问内存来读取完整的数据,从而降低访问效率。例如,如果一个整型变量起始地址不是4的倍数,在某些处理器上可能需要两次内存访问来读取该整型变量。
- 硬件要求:有些
CPU可以访问任意地址上的任意数据,而有些CPU只能在特定地址访问数据,因此不同硬件平台具有差异性,这样的代码就不具有移植性,如果在编译时,将分配的内存进行对齐,这就具有平台可以移植性了 - 优化内存使用:内存对齐可以减少内存碎片,提高内存利用率。因为未对齐的变量可能导致内存空间被浪费,例如在变量之间填充额外的空间,以确保下一个变量能够按照要求对齐。
- 跨平台兼容性:一些平台(如ARM、x86等)对内存对齐有不同的要求。在跨平台开发中,保持内存对齐可以提高代码的可移植性和兼容性。
8.为什么要使用内联函数 ?使用内联函数的缺点?
- 引入内联函数主要是解决一些频繁调用的小函数消耗大量空间的问题。通常情况下,在调用函数时,程序会将控制权从调用程序处转移到被调用函数处,在这个过程中,传递参数、寄存器操作、返回值等会消耗额外的时间和内存,如果调用的函数代码量很少,也许转移到调用函数的时间比函数执行的时间更长。而如果使用内联函数,内联函数会在调用处将代码展开,从而节省了调用函数的开销。
- 缺点:
- 如果使用很多内联函数,生成的二进制文件会变大;
- 编译的时间会增加,因为每次内联函数有修改,就需要重新编译代码。所以,并不是所有函数都要声明为内联函数,需要视具体情况而定。
- 引用:内联函数
9.如何避免野指针?
避免野指针(dangling pointers)的关键是良好的编程实践和使用正确的指针管理技术。以下是一些避免野指针的方法:
- 初始化指针:在定义指针变量时,始终确保对其进行初始化。如果无法立即分配有效的内存地址,请将指针设置为
nullptr或NULL。
int *ptr = nullptr;
- 及时释放资源:当不再需要指针指向的内存时,及时将其释放或重置为
nullptr。避免留下悬空的指针。
class test
{
//一系列函数
}
test *ptr = new test();//new一个函数
delete ptr;// 即使释放ptr
ptr = nullptr; //重置为nullptr
- 智能指针:使用智能指针来管理动态分配的内存,例如
std::unique_ptr、std::shared_ptr和std::weak_ptr。这些智能指针可以自动管理内存的生命周期,避免手动释放内存,从而减少野指针的风险。
std::unique_ptr<int> ptr(new int);
10.如何计算结构体长度?
可以参考:C/C++ struct内存对齐_struct内存对齐规则-CSDN博客
11.sizeof和strlen有什么区别?
sizeof 和 strlen 的区别在于:
sizeof是一个运算符,用于计算类型、变量或表达式的大小,而strlen是一个函数,用于计算以 null 结尾的字符串的长度。sizeof在编译时求值,对于所有类型的表达式都是有效的,而strlen在运行时遍历字符串,只能用于字符串。
int a;
size_t size_a = sizeof(a); // 返回变量 a 的字节大小
const char* str = "Hello";
size_t length = strlen(str); // 返回字符串的长度,不包括 null 终止符
12.知道条件变量吗?条件变量为什么要和锁配合使用?
1544

被折叠的 条评论
为什么被折叠?



