C90标准新增了const关键字,用于限定一个变量只读。在C语言中,用 const类型限定符申明的是变量,不是常量。
一般常见的两种使用方式
- 对于简单的非指针数据类型,应用const限定符很简单
- 对于指针类型,const使用复杂点——指针本身,或被指向的值,或两者都可以是const
程序 在执行时为其开辟的空间皆在内存(RAM)中,而RAM里的内存单元是可读可写 的;指针只是用来指定或定位要操作的数据的工具,只是用来读写RAM里内存单元的工作指针 。若对指针不加任何限定,程序中一个指针可以指向RAM中的任意位置(除了系统敏感区,如操作系统内核所在区域)并对其指向的内存单元进行读和写操作(由RAM的可读可写属性决定);RAM里内存单元的可读可写属性不会因为对工作指针的限定而变化,而所有对指针的各种const限定说白了只是对该指针的读写权限(包括读写位置)进行了限定。
以上说明似乎是在解释虽然被const限定的变量是可被修改的,下面程序验证下:
/* demo.c */
#include <stdio.h>
int main(char argc, char **argv)
{
const char a = 8;
a = 9;
printf("a=%u\n", a);
}
编译出错,不能直接修改a的值。
demo.c:8:2: error: assignment of read-only variable ‘a’
a = 9;
^
/* demo1.c */
#include <stdio.h>
int main(char argc, char **argv)
{
const char a = 8;
char *b = &a;
*b = 9;
printf("a=%u\n", a);
}
编译有警告,但编译通过。
demo1.c:7:12: warning: initialization discards ‘const’ qualifier from pointer target type [enabled by default]
char *b = &a;
^
指行结果如下:
a=9
由此可见,const修饰的变量是不具备不允许修改的特性的,可以通过指针绕道修改,以上证明到此就已经结束了。
/* demo2.c */
#include <stdio.h>
const char a = 8;
int main(char argc, char **argv)
{
char *b = &a;
*b = 9;
printf("a=%u\n", a);
}
编译有警告,但编译通过。
demo2.c:8:12: warning: initialization discards ‘const’ qualifier from pointer target type [enabled by default]
char *b = &a;
^
执行结果如下:
Segmentation fault (core dumped)
段错误,好像通过指针又不能修改了?
这是因为demo2.c的a是全局变量,const char a全局变量是放在只读区域.rodata
,所以不能被修改,虽然编译通过,但运行会出错。而demo1.c的const char a是属于局部变量,分配在栈上,可以通过指针修改栈上的局部变量。
/* demo3.c */
#include <stdio.h>
int main(char argc, char **argv)
{
const char* s1 = "test1";
char *s2 = s1;
s2 = "test2";
printf("%s\n",s1);
}
编译有警告,但编译通过。
demo3.c:7:13: warning: initialization discards ‘const’ qualifier from pointer target type [enabled by default]
char *s2 = s1;
^
执行结果如下:
test1
局部变量通过指针的方式的不能进行修改?
这是因为字符串"test1"是在只读区域开辟的空间被存放,第9行对s2赋值"test2"看似是对s1指向区域重新赋值,实际是在只读区域重新开辟的空间用来存放"test2",而s2被赋值指向这个空间。
/* demo4.c */
#include <stdio.h>
int main(char argc, char **argv)
{
const char s1[] = "test1";
char *s2 = s1;
s2[4] = '2';
printf("%s\n",s1);
}
编译有警告,但编译通过。
demo4.c:7:13: warning: initialization discards ‘const’ qualifier from pointer target type [enabled by default]
char *s2 = s1
执行结果如下:
test2
const限定的字符串可以被修改,是因为"test1"是在数组s1中存放,属于栈空间。