编程嵌入式C开发人员

描述C语言中const修饰符对函数参数和局部变量的影响。const如何影响指针和引用的传递,以及函数声明中不同的const修饰的区别是什么?

用 Hintsage AI 助手通过面试

答案

const在C语言中可以限制对象的可修改性。在处理函数参数时,这有助于保护数据不被意外修改。声明的关键区别取决于const修饰符所指向的对象,以及它相对于指针的位置。

各种声明示例:

void func(const int *ptr); // 指向常量int的指针 void func(int * const ptr); // 常量指针指向int void func(const int *const ptr); // 指向常量int的常量指针
  • const int *ptr — 数据不可修改,指针可以重新分配。
  • int *const ptr — 数据可修改,但指针不可重新分配。
  • const int *const ptr — 数据和指针在函数内都不可修改。

正确使用const的好处:

  • 清晰地表达开发者的意图,
  • 简化代码的阅读和维护,
  • 创建安全的内存操作接口。

代码示例

void print_array(const int *arr, size_t n) { for (size_t i = 0; i < n; ++i) { printf("%d\n", arr[i]); // arr[i] = 10; // 错误:试图修改const数据 } }

具有误导性的问题

问题: 可以将常量变量的地址赋值给普通指针吗?

预期错误答案: "是的,如果在指针声明中去掉const,编译器允许这样做。"

正确答案: 只允许通过显式类型转换(casting)进行“降级const”,但是试图修改被声明为const的对象会导致未定义行为。这样做是不可取的 — 这会破坏const的语义并导致运行时错误。

示例:

const int x = 5; int *ptr = (int*)&x; *ptr = 10; // UB:修改const对象

由于不理解主题细节而导致的实际错误示例


记录

在一个大型项目中,程序员尝试绕过const保护,将const指针强制转换为普通指针,并修改只读内存段的数据。在某些平台上,这导致程序崩溃(段错误),在其他平台上则出现难以调试的隐性错误。


记录

在一个处理数组的库中,开发者忘记将参数声明为const。结果是错误的函数调用意外修改了原始数据,导致数组状态不同步,以及在后续处理块中出现严重bug。


记录

在编写传递给第三方库的回调函数时,忘记为输入缓冲区指定const。库试图修改常量字符串中的数据,导致在某些操作系统上崩溃,并导致对问题源的长时间争议。