做效果图网站,霸县网站建设,网站开发的数据库,全国响应式网站建设面试题 1 #xff1a; C 中的变量存储类别有哪些#xff0c;并简要描述它们的特点#xff1f;
在C中#xff0c;变量的存储类别决定了变量的生命周期和可见性。以下是C中的几种变量存储类别及其特点#xff1a;
自动存储期
也称为局部存储类别。这类变量在函数或代码块…面试题 1 C 中的变量存储类别有哪些并简要描述它们的特点
在C中变量的存储类别决定了变量的生命周期和可见性。以下是C中的几种变量存储类别及其特点
自动存储期
也称为局部存储类别。这类变量在函数或代码块内部声明并且在函数或代码块执行时创建在函数或代码块退出时销毁。它们的生命周期是局部的只存在于声明它们的函数或代码块执行期间。每次进入函数或代码块时都会为这些变量分配新的存储空间退出时释放这些空间。
静态存储期
这类变量在程序开始执行时就创建并在程序结束时销毁。它们可以在全局作用域、命名空间作用域或函数作用域中声明。在全局或命名空间作用域中声明的静态变量在整个程序执行期间都存在。在函数作用域中声明的静态变量也称为静态局部变量只在该函数被调用的期间存在但其生命周期跨越了函数调用即它们的值在函数调用之间是保持的。
线程存储期
这类变量在线程开始执行时创建并在线程结束时销毁。它们通常用于多线程编程以确保每个线程都有自己的变量副本。在 C11 及以后的版本中可以使用 thread_local 关键字来声明线程局部存储期的变量。
动态存储期
这类变量由 new 运算符创建并由 delete 运算符销毁。它们的生命周期由程序员控制直到显式删除它们否则它们会一直存在。动态分配的变量在堆上分配空间不受函数或代码块生命周期的限制。
每种存储类别都有其特定的用途和优势。例如自动存储期的变量适用于需要临时存储数据的场景而静态存储期的变量则适用于需要在程序执行期间持续存在的数据。线程存储期的变量则适用于多线程环境中每个线程需要独立的数据副本时。动态存储期的变量则提供了更大的灵活性和控制力但也需要程序员手动管理内存。
面试题 2 const 和 constexpr 的区别是什么它们各自在哪些场景下更有用
在 C 中 const 和 constexpr 都是用于定义常量的关键字但它们在用途和语义上存在一些区别。 const 关键字 1可以用于声明一个变量为常量这意味着一旦变量被初始化其值就不能被修改。 2可以在运行时被赋值并且可以在程序的不同部分共享相同的内存地址。 3可以在任何函数内部或全局作用域中定义。 4主要用于确保变量在程序执行期间保持不变提高代码的可读性和可维护性。 constexpr 关键字 1用于声明一个常量表达式该表达式必须在编译时就能计算出其值。 2必须在编译时初始化并且其值必须是常量表达式。 3该关键字在编译时被存储在程序的只读数据段中因此它们的地址可以在程序的多个实例之间共享。 4主要用于编译时常量、数组大小、模板参数等需要在编译时知道值的情况。 const 和 constexpr 各自的使用场景 const 的使用场景 1当需要定义一个在程序执行期间保持不变的值时可以使用 const 。 2当需要在函数内部定义一个只在该函数内部有效的常量时可以使用 const 。 3当需要防止变量被意外修改时可以使用 const 。 constexpr 的使用场景 1当需要定义一个编译时常量时可以使用 constexpr 。 2当需要定义一个作为数组大小的常量时可以使用 constexpr 。 3当需要定义一个作为模板参数的常量时可以使用 constexpr 。 4当需要优化性能避免在运行时计算常量表达式的值时可以使用 constexpr 。 总结来说 const 用于在运行时定义不可变的变量而 constexpr 用于在编译时定义常量表达式。选择使用哪个关键字取决于你的具体需求以及是否需要在编译时还是运行时确定常量的值。
面试题 3 什么是内部链接和外部链接如何在 C 中使用 static 和 extern 关键字来控制链接
在C中链接 Linking 是编译器将不同的编译单元通常是源文件组合成一个可执行程序或库文件的过程。在这个过程中编译器需要解决函数或变量的引用和定义之间的关联。 内部链接和外部链接是 C 中符号链接性的两种类型它们决定了符号的作用域和可见性。 内部链接 当一个函数或变量被声明为 static 时它具有内部链接。这意味着该符号只在定义它的编译单元内可见其他编译单元无法访问它。在 C 中静态成员变量和静态成员函数具有内部链接。 外部链接 默认情况下函数或变量具有外部链接。这意味着函数或变量可以在多个编译单元之间共享只要它在链接时是可访问的。使用 extern 关键字可以声明一个函数或变量而不在当前编译单元中定义它从而在其他编译单元中定义该符号。 使用 static 和 extern 关键字来控制链接 使用 static 关键字 在函数或变量声明前加上 static 关键字可以使其具有内部链接。这样该函数或变量只在其定义的编译单元内可见。 例如在头文件中声明一个静态变量
// header.h
static int s_val 0;这样 s_val 只会在包含该头文件的源文件中可见而不会在其他源文件中共享。 使用 extern 关键字 extern 关键字用于声明一个在其他编译单元中定义的符号。它告诉编译器该符号在链接时将被解析而不是在当前编译单元中定义。 例如在一个源文件中定义一个函数并在另一个源文件中声明并使用该函数
// file1.cpp
#include header.hvoid func()
{// ... 函数实现 ...
}// file2.cpp
#include header.hextern void func(); // 声明在其他编译单元中定义的函数int main() {func(); // 调用在其他编译单元中定义的函数return 0;
}在这个例子中 func 在 file1.cpp 中定义并在 file2.cpp 中通过 extern 关键字声明。这样 main 函数可以调用 func 即使它没有在 file2.cpp 中定义。 注意在 C 中通常建议将变量声明为 extern 并在一个源文件中定义它以避免多重定义错误。对于函数可以在头文件中声明原型并在一个源文件中定义实现。这样其他源文件可以通过包含该头文件来使用该函数。
面试题 4 什么是 mutable 关键字它有什么用处
在 C 中 mutable 关键字用于在类的 const 成员函数中修改类的某个成员变量。通常 const 成员函数是不能修改它所属对象的任何成员变量的但是如果需要某些成员变量能够在 const 成员函数中被修改就可以将这些成员变量声明为 mutable 。 mutable 关键字允许在 const 成员函数中修改这些成员变量而不会影响对象的常量性。这对于某些需要在逻辑上保持常量性但实际上需要修改内部状态的场景非常有用。 如下为样例代码
#include iostreamclass Counter
{
public:Counter() : m_count(0), m_mutableVal(0) {}// 增加计数void increment(){m_count;}// 在const成员函数中修改 m_mutableValvoid setMutableVal(int val) const{m_mutableVal val;}// 获取MutableVal的值int getMutableVal() const{return m_mutableVal;}// 获取计数int getCount() const{return m_count;}private:int m_count; // 普通成员变量mutable int m_mutableVal; // mutable成员变量
};int main()
{const Counter counter; // 创建一个const对象// 调用const成员函数设置 m_mutableVal 的值counter.setMutableVal(1);printf(counter.getMutableVal() : %d\n,counter.getMutableVal());// 尝试调用非const成员函数会编译失败因为 counter 是 const 对象// counter.increment(); // 错误不能在const对象上调用非const成员函数return 0;
}上面代码的输出为
counter.getMutableVal() : 1在上面代码中 Counter 类有一个普通的成员变量 m_count 和一个被声明为 mutable 的成员变量 m_mutableVal 。在 const 成员函数 setMutableVal 中可以修改 m_mutableVal 的值而不会影响 m_count 的值或对象的常量性。当尝试在 const 对象 counter 上调用非 const 成员函数 increment 时编译器会报错因为这样做会违反 const 对象的常量性保证。
面试题 5 volatile 关键字的作用是什么
在 C 中 volatile 关键字用于告诉编译器对象的值可能会在编译器无法检测到的情况下被改变。通常有如下几种应用场景 硬件访问 当程序直接与硬件通信时硬件的状态可能会在任何时候改变而这些改变不是通过 C 代码直接进行的。例如一个嵌入式系统中的某个寄存器可能在外部中断或 DMA 传输完成后被更新。 多线程编程 在多线程环境中一个线程可能会修改一个变量而另一个线程正在读取或写入同一个变量。即使使用了互斥锁或其他同步机制 volatile 也可能被用来确保编译器不会对这个变量的访问进行优化从而导致不正确的行为。然而需要注意的是 volatile 本身并不提供线程间的同步或互斥它仅仅防止编译器优化。 信号处理 在信号处理程序中如果一个变量可能在信号处理程序之外被异步地修改那么这个变量应该被声明为 volatile 。 编译器优化 编译器通常会对代码进行优化假设变量的值在没有被显式修改的情况下是不会改变的。但是如果变量可能被外部因素如上面提到的情况修改那么这种优化可能是错误的。 volatile 关键字告诉编译器不要做出这样的假设。 注意 volatile 并不保证原子性。即使在 volatile 修饰的变量上执行的操作也可能不是原子的特别是当操作涉及多个步骤如递增一个值时。在多线程环境中确保数据的一致性和同步通常需要使用更高级的同步原语如互斥锁或原子操作。 此外过度使用 volatile 可能会导致性能下降因为编译器无法对涉及 volatile 变量的代码进行有效优化。因此应该只在确实需要的情况下使用它。