本文使用运行环境如下: 操作系统:Ubuntu Linux 18.04 64 bit 编译环境:gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)
C/C++语言支持const关键字,const意为“常数,不变的”,C++中可用于定义真正的常量,但在C语言中使用const修饰的标识符并不是真正意义上的常量,为只读变量,本文讨论C语言const关键字的常见用法。
本文组织架构:
const.c
#include <stdio.h> int main() { int arr[2] = {0}; return 0; }以上代码段只在main函数中定义了一个长度为2的int数组,C规定数组在编译时必须确定长度,这里显式地用2这个字面常量定义数组长度,编译运行是没有问题的。
$ gcc const.c $ ./a.out如果使用const修饰的变量定义数组,编译是否通过?
#include <stdio.h> int main() { const int i = 2; int arr[i] = {0}; return 0; }编译:
$ gcc const.c const.c: In function ‘main’: const.c:7:5: error: variable-sized object may not be initialized int arr[i] = {0}; ^~~ const.c:7:19: warning: excess elements in array initializer int arr[i] = {0}; ^ const.c:7:19: note: (near initialization for ‘arr’)显然,程序在编译阶段就停止了,const修饰的标识符i在编译阶段无法确定其值,它不是个常量。
const.c
#include <stdio.h> int main() { const int i = 2; printf("after, i = %d\n", i); int *p = (int *)&i; *p = 3; printf("after, i = %d\n", i); return 0; }编译运行:
$ gcc const.c $ ./a.out before, i = 2 after, i = 3可以看到使用const修饰的“常量”i的值被改变了,如果此时想直接通过赋值修改i的值
#include <stdio.h> int main() { const int i = 2; printf("before, i = %d\n", i); int *p = (int *)&i; *p = 3; printf("after, i = %d\n", i); i = 4;/* 编译报错,const修饰的变量量不能被赋值 */ printf("after2, i = %d\n", i); return 0; }编译:
$ gcc const.c const.c: In function ‘main’: const.c:15:7: error: assignment of read-only variable ‘i’ i = 4; ^编译是不能通过的,编译器提示这是个“只读变量”。
因此,C语言中使用const关键字修饰的标识符本质是只读变量,不能显式给const修饰的变量赋值,const关键字修饰的标识符并不是真正意义上的常量。
常用的只读变量的定义方式,不希望a被修改时添加const修饰。
从以上对memcpy函数形参src的分析中可知,使用const关键字修饰形参指针,可以保护源数据在函数运行过程中不被意外修改,从而增强程序的健壮性。
本文首先从两个方面论证了const关键字在C语言中只能定义只读变量,接着分析了几种C语言中常用的const声明,在适当的位置使用const关键字能够增强程序的健壮性。