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

SOC/IP验证工程师

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

公告

View Post

C语言中const的详细用法

C语言中const关键字的深度解析

const是C语言中用于定义常量的关键字,它使变量成为只读状态,防止程序意外修改重要数据。正确使用const能显著提高代码的健壮性、可读性和安全性。

一、基础用法:定义常量

1. 基本常量定义

const int MAX_SIZE = 100;    // 整型常量
const float PI = 3.14159;    // 浮点常量
const char NEWLINE = '\n';   // 字符常量

2. 常量与宏定义的区别

特性 const常量 #define宏
类型检查 有 无(预处理器替换)
作用域 块作用域 文件作用域
调试可见性 调试器中可见 预编译后消失
内存分配 占用内存空间 不占用内存
数组大小定义 C99前不能用于数组大小 可用于数组大小
// const定义(C99前不合法,C99后合法)
const int SIZE = 10;
int arr[SIZE];  // C99前错误,C99后正确

// 宏定义(始终合法)
#define SIZE 10
int arr[SIZE];  // 始终正确

二、高级用法:指针与const

const与指针结合使用有4种组合方式,每种都有不同的保护级别:

1. 指向常量的指针(Pointer to constant)

int value = 10;
const int *ptr = &value;  // ptr指向的内容不可变

// *ptr = 20; // 错误:不能通过ptr修改value
value = 20;   // 正确:value本身不是常量
ptr = NULL;   // 正确:指针本身可变

2. 常量指针(Constant pointer)

int a = 5, b = 10;
int *const ptr = &a;  // ptr本身不可变

*ptr = 15;   // 正确:可以修改指向的值
// ptr = &b; // 错误:不能改变指针指向

3. 指向常量的常量指针(Constant pointer to constant)

const int value = 100;
const int *const ptr = &value;  // 指针和内容都不可变

// *ptr = 200; // 错误:不能修改内容
// ptr = NULL; // 错误:不能修改指针

4. 常量指针指向变量(较少用)

int data = 42;
int *const ptr = &data;  // 指针不变,内容可变

*ptr = 99;   // 正确
// ptr = &data2; // 错误

三、const在函数中的应用

1. 保护函数参数

// 保护原始数据不被修改
void print_string(const char *str) {
    // str[0] = 'A'; // 错误:不能修改
    printf("%s\n", str);
}

// 保护指针不被修改
void init_array(int *const arr, int size) {
    // arr = NULL; // 错误:不能修改指针
    for(int i=0; i<size; i++) {
        arr[i] = 0;
    }
}

2. 返回const指针

// 返回指向常量的指针
const char *get_error_message(int code) {
    static const char *messages[] = {
        "Success",
        "Invalid input",
        "Out of memory"
    };
    return messages[code];
}

// 使用
const char *msg = get_error_message(1);
// msg[0] = 'X'; // 错误:不能修改

四、const与复合数据类型

1. 结构体中的const

struct Point {
    int x;
    int y;
};

// 整个结构体为常量
const struct Point origin = {0, 0};
// origin.x = 1; // 错误

// 结构体成员为常量
struct ImmutablePoint {
    const int x;
    const int y;
};

struct ImmutablePoint p = {10, 20};
// p.x = 30; // 错误

2. 数组中的const

// 常量数组
const int days[] = {31,28,31,30,31,30,31,31,30,31,30,31};
// days[1] = 29; // 错误

// 指向常量数组的指针
const char *const months[] = {
    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
// months[0] = "January"; // 错误
// months = NULL;        // 错误

五、const的底层机制

1. 存储位置

  • 全局const变量:通常存储在只读数据段(.rodata)
  • 局部const变量:存储在栈上,但编译器阻止修改
  • 动态分配的const:存储在堆上,但语义上只读

2. 强制修改(危险操作)

const int immutable = 100;
int *ptr = (int*)&immutable; // 强制转换去除const
*ptr = 200; // 未定义行为!可能崩溃或无效修改

printf("%d vs %d\n", immutable, *ptr); 
// 可能输出:100 vs 200(编译器优化导致)

六、最佳实践与常见陷阱

1. 最佳实践

// 1. 函数参数:指针参数应加const保护
size_t strlen(const char *s);

// 2. 硬件寄存器映射
volatile const uint32_t *HW_REGISTER = (uint32_t*)0xFFFF0000;

// 3. 跨文件共享常量(头文件中)
// config.h
extern const int MAX_USERS;

// config.c
const int MAX_USERS = 1000;

2. 常见错误

// 错误1:忘记初始化
const int MIN_VALUE; // 错误:未初始化常量

// 错误2:修改const指针内容
const int arr[] = {1,2,3};
int *p = arr; // 警告:丢弃const限定符
*p = 4;       // 运行时错误(写入只读内存)

// 错误3:返回局部const指针
const char *get_name() {
    const char name[] = "Alice"; // 局部数组
    return name; // 返回悬垂指针!
}

七、const在嵌入式开发中的特殊应用

1. 只读硬件寄存器

// 定义只读硬件寄存器
#define HW_VERSION (*(volatile const uint32_t *)0x400FE000)

void print_version() {
    printf("Hardware Version: 0x%08X\n", HW_VERSION);
}

2. 配置表保护

// 存储在Flash中的配置表
const struct {
    uint16_t baud_rate;
    uint8_t parity;
    uint8_t stop_bits;
} UART_CONFIG = {115200, 0, 1};

// 防止意外修改
void init_uart() {
    setup_uart(UART_CONFIG.baud_rate, 
               UART_CONFIG.parity,
               UART_CONFIG.stop_bits);
}

八、const与类型限定符组合

1. const + volatile

// 只读但可能被外部改变的硬件寄存器
volatile const uint32_t *STATUS_REG = (uint32_t*)0x40005000;

uint32_t current_status = *STATUS_REG; // 每次读取最新值
// *STATUS_REG = 0; // 错误:const禁止写入

2. const + static

// 文件内可见的常量
static const int INTERNAL_CONST = 42;

// 函数内持久化的常量
void counter() {
    static const int MAX_COUNT = 100; // 只初始化一次
    static int count = 0;
    if(++count > MAX_COUNT) reset();
}

总结:const的核心价值

  1. 安全性:防止意外修改关键数据
  2. 可读性:明确标识不应修改的值
  3. 优化提示:帮助编译器进行优化
  4. 接口设计:清晰表达函数参数和返回值的意图
  5. 硬件交互:安全访问只读硬件资源
graph TD A[const用法] --> B[基本常量] A --> C[指针保护] A --> D[函数参数] A --> E[返回值] A --> F[复合类型] C --> C1[指向常量的指针] C --> C2[常量指针] C --> C3[双重const] F --> F1[结构体常量] F --> F2[常量数组] F --> F3[const成员]

posted on 2025-06-23 22:43  SOC验证工程师  阅读(500)  评论(1)    收藏  举报

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