C语言const
Love coldplay 人气:01 介绍
const关键字是constant的缩写,翻译为常量、常数。在C语言中const的作用很强大,它可以修饰变量、数组、指针、函数参数等。
1.1 const修饰变量
const修饰变量,表示希望此变量具有只读性,防止被直接直接修改。
//const关键字是constant的缩写,翻译为常量、常数。 //在C语言中const的作用很强大,它可以修饰变量、数组、指针、函数参数等。 #include<stdio.h> int main() { const int num = 100; num = 20; printf("%d\n", num); }
发现const 修饰的变量,随后试图修改num的值,结果出现红色波浪线,编译器提醒我们:表达式必须是可修改的左值。
所以我们得出结论:const修饰的变量,不能被修改。
const修饰的变量就一定不能被修改吗???
const int num = 100; int *p = # *p= 20; printf("%d\n", num);
运行结果
通过上图我们发现num的值被修改了,通过指针可以间接的修改const修饰的变量。
但是运行时会出现警告:warning C4090: “初始化”: 不同的“const”限定符。
是因为num类型是const修饰,但是p是整型指针变量 ,
类型不同。所以通过下面强转就没警告了。
改进后的代码
const int num = 100; int *p = (int*)# *p= 20; printf("%d\n", num);
总结:const修饰的变量不能被直接修改
1.2 const修饰数组
#include<stdio.h> int main() { const int array[5] = { 0,1,2,3,4 }; array[0] = 100; }
表示const修饰的数组也不能被修改。
通过上面1.1const修饰变量的分析,同理也联想到:指针是否可以修改数组的内容。结果如下:
#include<stdio.h> int main() { const int array[5] = { 0,1,2,3,4 }; //array[0] = 100; int *p = array; *p = 100; printf("%d\n", array[0]); }
不难发现,指针可以修改。和1.1节出现结果一样,同样运行时程序出现了警告:warning C4090: “初始化”: 不同的“const”限定符,同样的警告出现了。
经过强转后:
#include<stdio.h> int main() { const int array[5] = { 0,1,2,3,4 }; //array[0] = 100; int *p = (int *)array;//array原本的数据类型为const int[5] *p = 100; printf("%d\n", array[0]); }
总结:const修饰数组时,其值不能被直接修改
1.3 const修饰指针
此部分分为两种情况去分析:
#include<stdio.h> int main() { int a = 100; const int *p = &a; *p = 1000; printf("%d\n", a); }
此时,通过上图容易发现const修饰指针指向的内容一旦修改,就会自动报错,所以*p(指针指向的内容不能被修改),但指针变量p本身是可以被修改的。
#include<stdio.h> int main() { int a = 100; int* const p = &a;//p的数据类型为int *const *p = 1000; printf("%d\n", a); }
此时,const修饰的是指针p本身,所以指针本身不能被修改,但是指针所指向的内容*p可被修改
1.4 const修饰函数参数
#include<stdio.h> int myFunc(const int* p) { *p = *p + 1; return *p; }
const修饰函数参数,对参数起到限定的作用, 通过发现指针也能修改其值。
总结:const修饰函数参数,本质上和修饰变量和指针一样。表示其值不能被直接修改。
2 const对程序的影响
可以发现,在*p下面出现了红色波浪线,让上述的错误提前出现,避免程序在运行时出错。
总结:编译器可以对const修饰的变量进行合理性检查,让错误提前出现。
3 总结
通过这篇博客,我对const修饰变量、数组、指着和函数参数进行了归纳总结。总体来说有几个点需要注意:
const修饰变量,不能被直接修改
const修饰指针指向的内容时(const int * p=&a),指针指向内容(*p)不能被修改,但指针本身(p)可以被修改。
const修饰指针本身时(int * const p =&a),指针指向的内容(*p)可以被修改,但是指针本身(p)不能被修改。
const 修饰字符串 (const *p=“abcd”;)和(const p[]=“abcd”;)这两种情况的分析,前者字符串不能修改,后者字符串可以修改。这 是由C语言使用存储器的方式决定的。
补充内容
char *cards = “JQK”; 的情况下计算机操作的步骤:
计算机做的步骤:
计算机加载字符串字面值:
当计算机把程序载入存储器时,会把所有常数值(如字符串常量"JQK")放到常量存储区,这部分存储器是只读的。
程序在栈上创建cards变量
栈是存储器中计算机用来保存局部变量的部分,局部变量也就是位于函数内部的变量,cards变量就在这个地方。
cards变量设为"JQK"的地址
cards变量将会保存字符串字面值"JQK"的地址。为了防止修改,字符串字面值通常保存在只读存储器中。
计算机试图修改字符串
程序试图修改cards变量指向的字符串中的内容时就会失败,因为字符串是只读的。
char cards[] = “JQK”;的情况下计算机操作的步骤:
计算机加载字符串字面值:
当计算机把程序载入存储器时,会把所有常数值(如字符串常量"JQK")放到常量存储区,这部分存储器是只读的。
程序在栈上新建了一个数组
我们声明了数组,所以程序会创建一个足够大的数组来保存字符串"JQK"
程序初始化数组
除了为数组分配空间,程序还会把字符串字面值"JQK"的内容复制到栈上。
补充内容
char *cards = “JQK”; 的情况下计算机操作的步骤:
计算机做的步骤:
计算机加载字符串字面值:
当计算机把程序载入存储器时,会把所有常数值(如字符串常量"JQK")放到常量存储区,这部分存储器是只读的。
程序在栈上创建cards变量
栈是存储器中计算机用来保存局部变量的部分,局部变量也就是位于函数内部的变量,cards变量就在这个地方。
cards变量设为"JQK"的地址
cards变量将会保存字符串字面值"JQK"的地址。为了防止修改,字符串字面值通常保存在只读存储器中。
计算机试图修改字符串
程序试图修改cards变量指向的字符串中的内容时就会失败,因为字符串是只读的。
char cards[] = “JQK”;的情况下计算机操作的步骤:
计算机加载字符串字面值:
当计算机把程序载入存储器时,会把所有常数值(如字符串常量"JQK")放到常量存储区,这部分存储器是只读的。
程序在栈上新建了一个数组
我们声明了数组,所以程序会创建一个足够大的数组来保存字符串"JQK"
程序初始化数组
除了为数组分配空间,程序还会把字符串字面值"JQK"的内容复制到栈上。
区别:
原来的代码使用了指向只读字符串字面值的指针;而在第二段代码中,用字符串字面值初始化了一个数组,从而得到了这些字母的副本,这样就可以随意修改他们了。
加载全部内容