嵌入式面试高频!!!C语言(一)

一.全局变量和局部变量的区别:

  1. 在编程中,全局变量局部变量是根据作用域(变量可访问的范围)来区分的两种变量类型。它们的主要区别如下:

        1. 定义位置与作用域

  • 全局变量

    • 定义位置:在代码文件的顶层(所有函数、类或模块外部)。
    • 作用域:整个程序(或当前模块),所有函数和类都可访问。
  • 局部变量

    • 定义位置:在函数、类方法或代码块(如循环、条件语句)内部。
    • 作用域:仅限于定义它的函数或代码块,外部无法访问。

2. 生命周期

  • 全局变量

    • 程序启动时创建,程序结束时销毁。
    • 始终占用内存,即使未被使用。
  • 局部变量

    • 函数 / 代码块被调用时创建,执行结束后销毁。
    • 仅在需要时占用内存,提高资源利用率。

3. 访问权限

  • 全局变量

    • 可被程序中任何位置读取和修改(需注意不同语言的访问修饰符,如 Python 的global、Java 的public)。
    • 跨函数共享数据方便,但可能导致命名冲突或意外修改。
  • 局部变量

    • 只能在定义它的作用域内访问。
    • 不同函数的局部变量同名不冲突,提高代码安全性。

4. 内存分配

  • 全局变量

    • 通常存储在数据段(已初始化)或 BSS 段(未初始化)。
    • 内存地址固定,程序运行期间不变。
  • 局部变量

    • 存储在栈内存(静态分配)或堆内存(动态分配,如 Python 的对象)。
    • 函数调用结束后,栈空间自动释放。

5. 使用场景

  • 全局变量

    • 配置参数(如系统常量)。
    • 需在多个函数间共享的数据(如数据库连接)。
    • 单例模式(如日志记录器)。
  • 局部变量

    • 函数内部临时计算的中间值。
    • 避免数据被外部意外修改。
#include 

// 全局变量示例
int global_var = 10;  // 全局变量,在所有函数外部定义

void func1() {
    printf("func1: global_var = %d\n", global_var);  // 可直接访问全局变量
}

void func2() {
    global_var += 5;  // 直接修改全局变量
    printf("func2: 修改后的 global_var = %d\n", global_var);
}

int main() {
    func1();  // 输出: func1: global_var = 10
    
    func2();  // 输出: func2: 修改后的 global_var = 15
    
    // 局部变量示例
    {
        int local_var = 20;  // 局部变量,在代码块内部定义
        printf("main: 局部变量 local_var = %d\n", local_var);
    }  // 局部变量作用域结束
    
    // printf("main: local_var = %d\n", local_var);  // 错误:无法访问已超出作用域的局部变量
    
    return 0;
}

7. 优缺点

特性 全局变量 局部变量
数据共享 方便跨模块 / 函数访问 需通过参数传递,较繁琐
安全性 易被意外修改,增加调试难度 隔离性好,减少命名冲突和副作用
内存管理 长期占用内存,可能导致资源浪费 按需分配,提高内存效率
代码可读性 滥用会导致依赖关系复杂,降低可维护性 作用域明确,代码逻辑清晰

8. 最佳实践

  • 优先使用局部变量:减少全局状态,提高代码模块化和可测试性。
  • 限制全局变量使用:若需全局数据,可通过参数传递或类的静态属性实现。
  • 避免全局变量与局部变量同名:防止混淆和意外覆盖。

二.在 C 语言中,static关键字是一个多功能的修饰符,主要用于控制变量和函数的存储方式作用域生命周期。以下是其核心用法的总结:

1. 修饰局部变量

  • 存储方式:将局部变量存储在静态存储区(而非栈上)。
  • 生命周期:变量在程序启动时创建,程序结束时销毁,而非随函数调用结束而释放。
  • 初始化:仅在首次调用函数时初始化,后续调用保留上次的值。
  • 作用域:仍为局部作用域(仅函数内可见)。
void counter() {
    static int count = 0;  // 仅首次调用时初始化
    count++;
    printf("Count: %d\n", count);
}

int main() {
    counter();  // 输出: 1
    counter();  // 输出: 2
    counter();  // 输出: 3
    return 0;
}

2. 修饰全局变量

  • 存储方式:存储在静态存储区(与普通全局变量相同)。
  • 生命周期:程序全程存在。
  • 作用域限制在定义它的源文件内,其他文件无法通过extern引用(即 “内部链接”)。
// file1.c
static int static_global = 10;  // 仅file1.c可见

// file2.c
extern int static_global;  // 错误:无法引用file1.c的static变量

3. 修饰函数

  • 作用域:将函数的作用域限制在定义它的源文件内,其他文件无法调用。

示例

// file1.c
static void helper() {  // 仅file1.c可调用
    printf("Helper function\n");
}

// file2.c
extern void helper();  // 错误:无法引用file1.c的static函数

4. 修饰结构体成员(C++ 特性,C 语言不支持)

在 C++ 中,static可修饰结构体 / 类的成员变量或函数,使其为所有实例共享(属于类而非对象)。但C 语言不支持此特性

static 与普通变量的对比

特性 普通局部变量 static 局部变量 普通全局变量 static 全局变量
存储位置 栈内存 静态存储区 静态存储区 静态存储区
生命周期 函数调用期间 整个程序运行期 整个程序运行期 整个程序运行期
作用域 函数内部 函数内部 整个程序(需 extern) 定义它的文件内部
初始化 每次调用重新初始化 仅首次调用时初始化 未显式初始化时为 0 未显式初始化时为 0

常见面试题

  1. 静态变量的初始值:静态变量(全局或局部)未显式初始化时,默认初始化为0(或NULL)。
  2. 静态局部变量的线程安全性:在多线程环境中,静态局部变量的初始化可能存在竞态条件(C++11 后通过static关键字保证线程安全,但 C 语言需手动同步)。
  3. staticconst的区别
    • static:控制存储和作用域。
    • const:修饰变量为只读,不可修改。

典型应用场景

  1. 计数器或累加器:在函数内部记录调用次数。
  2. 单例模式:确保一个类(或结构体)仅有一个实例。
  3. 模块化编程:将函数或全局变量隐藏在模块内部,避免命名冲突。
  4. 缓存数据:在多次函数调用间保留中间结果,提高效率。

你可能感兴趣的:(嵌入式八股文,面试,c语言,职场和发展,嵌入式硬件,物联网,单片机)