C语言中const的详细用法

2025-11-29 03:57:47

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

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的核心价值

安全性:防止意外修改关键数据

可读性:明确标识不应修改的值

优化提示:帮助编译器进行优化

接口设计:清晰表达函数参数和返回值的意图

硬件交互:安全访问只读硬件资源

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成员]

Copyright © 2022 角动游戏活动平台 - 全网网游动态实时追踪 All Rights Reserved.