• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

SOC/IP验证工程师

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

C语言中static的详细用法

static是C语言中非常重要的关键字,根据使用上下文有不同的含义。以下是static的详细用法:

1. 静态局部变量

基本特性

#include <stdio.h>

void counter() {
    static int count = 0;  // 只初始化一次
    count++;
    printf("Count: %d\n", count);
}

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

详细特点

  • 生命周期:整个程序运行期间
  • 作用域:仅限于定义它的函数内部
  • 存储位置:数据段(而非栈)
  • 初始化:只初始化一次,默认初始化为0

实际应用场景

// 1. 函数调用计数器
void debug_function(const char *func_name) {
    static int call_count = 0;
    call_count++;
    printf("[DEBUG] %s called %d times\n", func_name, call_count);
}

// 2. 状态保持
int get_next_id() {
    static int current_id = 1000;
    return current_id++;
}

// 3. 单次初始化
void initialize_once() {
    static bool initialized = false;
    if (!initialized) {
        printf("Performing one-time initialization...\n");
        initialized = true;
    }
}

2. 静态全局变量

文件作用域变量

// file1.c
#include <stdio.h>

static int file_local_var = 42;  // 只在file1.c中可见

void print_var() {
    printf("file_local_var = %d\n", file_local_var);
}

void modify_var(int new_val) {
    file_local_var = new_val;
}
// file2.c
#include <stdio.h>

// 错误:无法访问file1.c中的静态全局变量
extern int file_local_var;  // 链接错误!

void try_access() {
    // printf("%d\n", file_local_var);  // 编译错误
}

模块化编程中的应用

config.h

#ifndef CONFIG_H
#define CONFIG_H

// 公开接口
int get_config_value(void);
void set_config_value(int value);

#endif

config.c

#include "config.h"

// 隐藏实现细节
static int config_data = 100;
static bool config_initialized = false;

static void initialize_config(void) {
    if (!config_initialized) {
        config_data = 200;
        config_initialized = true;
    }
}

int get_config_value(void) {
    initialize_config();
    return config_data;
}

void set_config_value(int value) {
    initialize_config();
    config_data = value;
}

3. 静态函数

文件内私有函数

// math_utils.c
#include <math.h>

// 公开函数
double calculate_hypotenuse(double a, double b) {
    return sqrt(square(a) + square(b));
}

// 私有函数 - 只在当前文件内可见
static double square(double x) {
    return x * x;
}

// 另一个私有函数
static bool is_valid_triangle(double a, double b, double c) {
    return (a + b > c) && (a + c > b) && (b + c > a);
}

大型项目中的模块化

module_a.c

#include <stdio.h>

// 公开接口
void module_a_public_function(void) {
    internal_helper();
    printf("Public function of Module A\n");
}

// 私有实现 - 其他模块无法调用
static void internal_helper(void) {
    printf("Internal helper function\n");
}

static int internal_calculation(int x, int y) {
    return x * y + 42;
}

module_b.c

// 无法访问module_a.c中的静态函数
// extern void internal_helper(void);  // 错误!

4. 综合应用实例

单例模式实现

// singleton.c
#include <stdio.h>
#include <stdbool.h>

typedef struct {
    int data;
    char name[32];
} singleton_t;

static singleton_t *instance = NULL;

static singleton_t* create_instance(void) {
    static singleton_t actual_instance = {
        .data = 0,
        .name = "Singleton"
    };
    return &actual_instance;
}

singleton_t* get_instance(void) {
    if (instance == NULL) {
        instance = create_instance();
    }
    return instance;
}

void singleton_operation(void) {
    singleton_t *inst = get_instance();
    inst->data++;
    printf("Singleton operation: data=%d, name=%s\n", inst->data, inst->name);
}

对象池实现

// object_pool.c
#include <stdio.h>
#include <stdbool.h>

#define POOL_SIZE 10

typedef struct {
    int id;
    bool in_use;
    char data[64];
} object_t;

// 静态对象池
static object_t object_pool[POOL_SIZE];
static bool pool_initialized = false;

static void initialize_pool(void) {
    if (!pool_initialized) {
        for (int i = 0; i < POOL_SIZE; i++) {
            object_pool[i].id = i;
            object_pool[i].in_use = false;
            snprintf(object_pool[i].data, sizeof(object_pool[i].data), 
                    "Object_%d", i);
        }
        pool_initialized = true;
    }
}

object_t* acquire_object(void) {
    initialize_pool();
    
    for (int i = 0; i < POOL_SIZE; i++) {
        if (!object_pool[i].in_use) {
            object_pool[i].in_use = true;
            return &object_pool[i];
        }
    }
    return NULL; // 池已满
}

void release_object(object_t *obj) {
    if (obj != NULL) {
        obj->in_use = false;
    }
}

5. 嵌入式系统中的应用

硬件寄存器封装

// uart_driver.c
#include <stdint.h>

// 硬件寄存器地址
#define UART_BASE 0x40001000
#define UART_DATA_REG   (*(volatile uint32_t*)(UART_BASE + 0x00))
#define UART_STATUS_REG (*(volatile uint32_t*)(UART_BASE + 0x04))
#define UART_CTRL_REG   (*(volatile uint32_t*)(UART_BASE + 0x08))

// 私有状态
static bool uart_initialized = false;
static uint32_t baud_rate = 115200;

static void uart_hw_init(void) {
    UART_CTRL_REG = (baud_rate << 16) | 0x03;
    uart_initialized = true;
}

// 公开接口
void uart_init(uint32_t baud) {
    baud_rate = baud;
    uart_hw_init();
}

void uart_putchar(char c) {
    if (!uart_initialized) {
        uart_hw_init();
    }
    
    // 等待发送缓冲区空
    while (!(UART_STATUS_REG & 0x02));
    
    UART_DATA_REG = c;
}

char uart_getchar(void) {
    if (!uart_initialized) {
        uart_hw_init();
    }
    
    // 等待接收数据
    while (!(UART_STATUS_REG & 0x01));
    
    return (char)UART_DATA_REG;
}

6. 内存管理应用

固定大小内存分配器

// fixed_allocator.c
#include <stddef.h>
#include <stdbool.h>

#define BLOCK_SIZE 64
#define NUM_BLOCKS 100

// 内存池
static unsigned char memory_pool[BLOCK_SIZE * NUM_BLOCKS];
static bool block_used[NUM_BLOCKS];

// 私有辅助函数
static size_t find_free_block(void) {
    for (size_t i = 0; i < NUM_BLOCKS; i++) {
        if (!block_used[i]) {
            return i;
        }
    }
    return NUM_BLOCKS; // 表示未找到
}

// 公开接口
void* fixed_alloc(void) {
    size_t block_idx = find_free_block();
    if (block_idx < NUM_BLOCKS) {
        block_used[block_idx] = true;
        return &memory_pool[block_idx * BLOCK_SIZE];
    }
    return NULL;
}

void fixed_free(void *ptr) {
    if (ptr != NULL) {
        size_t block_idx = ((unsigned char*)ptr - memory_pool) / BLOCK_SIZE;
        if (block_idx < NUM_BLOCKS) {
            block_used[block_idx] = false;
        }
    }
}

7. 高级用法和技巧

编译时常量

// 使用static const创建编译时常量
static const int MAX_BUFFER_SIZE = 1024;
static const double PI = 3.141592653589793;

void process_buffer(char *buffer) {
    static const char DELIMITER = '\n';
    
    for (int i = 0; i < MAX_BUFFER_SIZE; i++) {
        if (buffer[i] == DELIMITER) {
            break;
        }
        // 处理数据
    }
}

函数指针表

// command_handler.c
#include <stdio.h>

typedef void (*command_func_t)(void);

static void cmd_help(void) {
    printf("Available commands: help, version, quit\n");
}

static void cmd_version(void) {
    printf("Version 1.0.0\n");
}

static void cmd_quit(void) {
    printf("Goodbye!\n");
}

// 私有命令表
static const struct {
    const char *name;
    command_func_t func;
} commands[] = {
    {"help", cmd_help},
    {"version", cmd_version},
    {"quit", cmd_quit},
    {NULL, NULL}
};

// 公开接口
void execute_command(const char *cmd_name) {
    for (int i = 0; commands[i].name != NULL; i++) {
        if (strcmp(commands[i].name, cmd_name) == 0) {
            commands[i].func();
            return;
        }
    }
    printf("Unknown command: %s\n", cmd_name);
}

8. 注意事项和最佳实践

线程安全性

#include <threads.h>

// 非线程安全的静态变量使用
static int non_thread_safe_counter = 0;

void unsafe_increment(void) {
    non_thread_safe_counter++;  // 多线程环境下有竞态条件
}

// 线程安全的版本(需要外部同步)
static mtx_t counter_mutex;
static int thread_safe_counter = 0;

void safe_increment(void) {
    mtx_lock(&counter_mutex);
    thread_safe_counter++;
    mtx_unlock(&counter_mutex);
}

初始化顺序问题

// 注意:静态变量的初始化顺序在同一个文件内是确定的
// 但在不同文件间是不确定的

// file1.c
static int global_a = init_a();  // 初始化顺序不确定

// file2.c  
static int global_b = init_b();  // 可能先于global_a初始化

总结

static关键字的主要用途:

  1. 静态局部变量:保持函数调用间的状态
  2. 静态全局变量:限制变量作用域到当前文件
  3. 静态函数:创建文件私有函数

优点:

  • 信息隐藏和封装
  • 避免命名冲突
  • 控制变量生命周期
  • 提高模块化程度

注意事项:

  • 线程安全性问题
  • 初始化顺序不确定性
  • 可能增加内存使用(静态变量常驻内存)

合理使用static可以写出更安全、更模块化、更易维护的C代码。

posted on 2025-10-03 21:32  SOC验证工程师  阅读(30)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3