序言
他们都晓得采用constURL限量发行两个表达式为黎贞,但它是或者说象征意义上的黎贞吗?前述中又该怎样采用constURL?在答疑那些难题以后,他们须要先认知constURL的基本上采用。责任编辑表明C中的constURL,不主要就包括C++。
基本上如是说
const是constant的缩写,是维持不变的原意。但并并非说它润色自变量,而要说它限量发行两个表达式为黎贞。
润色一般表达式
比如:
const int NUM = 10; //与int const NUM同构
NUM = 9; //校对严重错误,不容再度修正
虽然采用了const润色NUM,使NUM为黎贞,因而试著对NUM再度表达式的操作方式是违法的,校对器Sonbhadra收起。正因如此,假如须要采用const润色两个表达式,所以它根本无法在已经开始新闻稿时就表达式,不然前面就没良机了(前面会讲到两个特定情形)。
润色字符串
比如采用constURL润色字符串,使其原素不容许被发生改变:
const int arr[] = {0,0,2,3,4}; //与int const arr[]同构
arr[2] = 1; //校对严重错误
企图修正arr的文本的操作方式是违法的,校对器Sonbhadra收起:
error: assignment of read-only location ‘arr[2]’
润色操作方式符
润色操作方式符的情形较为多,主要就有下列三种情形:
1.const 润色 *p,对准的第一类黎贞,操作方式符的对准气门:
int a = 9;
int b = 10;
const int *p = &a;//p是两个对准int类别的const值,与int const *p同构
*p = 11; //校对严重错误,对准的第一类是黎贞的,不容透过p展开发生改变
p = &b; //不合法,发生改变了p的对准
这里为了便于认知,可认为const润色的是*p,通常采用*对操作方式符展开解引用来访问第一类,因而,该第一类是黎贞的。
2.const润色p,对准的第一类气门,操作方式符的对准不容变:
int a = 9;
int b = 10;
int * const p = &a;//p是两个const操作方式符
*p = 11; //不合法,
p = &b; //校对严重错误,p是两个const操作方式符,黎贞,不容变
3.操作方式符不容发生改变对准,对准的文本也不气门
int a = 9;
int b = 10;
const int * const p = &a;//p既是两个const操作方式符,同时也对准了int类别的const值
*p = 11; //校对严重错误,对准的第一类是黎贞的,不容透过p展开发生改变
p = &b; //校对严重错误,p是两个const操作方式符,黎贞,不容变
看完上面三种情形之后是否会觉得混乱,并且难以记忆呢?他们采用一句话总结:
const放在*的左侧任意位置,限量发行了该操作方式符对准的第一类是黎贞的;const放在*的右侧,限量发行了操作方式符本身是黎贞的,即不容变的。
假如还并非很好认知,他们可以这样来看,去掉类别表明符,查看const润色的文本,上面三种情形去掉类别表明符int之后,如下:
const *p; //润色*p,操作方式符对准的第一类不容变
* const p; //润色p,操作方式符不容变
const * const p; //第两个润色了*p,第二个润色了p,两者都不容变
const右边润色谁,就表明谁是不容变的。上面的说法仅仅是帮助认知和记忆。借助上面这种认知,就会发现下列三种同构情形:
const int NUM = 10; //与int const NUM同构
int a = 9;
const int *p = &a;//与int const *p同构
const int arr[] = {0,0,2,3,4}; //与int const arr[]同构
constURL究竟有什么用
前面如是说了这么多文本,是并非都常用呢?constURL究竟有什么用?
润色函数形参
前述上,为他们可以经常发现constURL的身影,比如很多库函数的新闻稿:
char *strncpy(char *dest,const char *src,size_t n);//字符串拷贝函数
int *strncmp(const char *s1,const char *s2,size_t n);//字符串较为函数
透过看strncpy函数的原型可以晓得,源字符串src是黎贞的,不容变的,而dest并没该限制。他们透过两个小例子继续观察:
//test.c
#include<stdio.h>
void myPrint(const char *str);
void myPrint(const char *str)
{
str[0] = H;
printf(“my print:%s\n”,str);
}
int main(void)
{
char str[] = “hello world”;
myPrint(str);
return 0;
}
在这个例子中,他们不希望myPrint函数修正传入的字符串文本,因而入参采用了const限量发行符,表明传入的字符串是黎贞的,因而,假如myPrint函数内部假如试著对str展开修正,Sonbhadra收起:
$ gcc -o test test.c
test.c:6:12: error: assignment of read-only location ‘*str’
str[0] = H;
因而,他们自己在编码过程中,假如确定传入的操作方式符参数仅用于访问数据,所以应该将其新闻稿为两个对准const限量发行类别的操作方式符,避免函数内部对数据展开意外地修正。
润色全局表达式
他们晓得,采用全局表达式是一种不安全的做法,因为程序的任何部分都能够对全局数据展开修正。而假如对全局变量增加const限量发行符(假设该全局数据不希望被修正),就可以避免被程序其他部分修正。这里有两种采用方式。
第一种,在a文件中定义,其他文件中采用外部新闻稿,比如:
a.h
//a.h
const int ARR[] = {0,1,2,3,4,5,6,7,8,9}; //定义int字符串
b.c
//b.c
extern const int ARR[]; //注意,这里不能再对ARR展开表达式
//前面可以采用ARR
第二种,在a文件中定义,并采用static润色,b文件包含a文件,比如:
a.h
//a.h
static const int ARR[] = {0,1,2,3,4,5,6,7,8,9}; //定义int字符串
b.c
//b.c
#include<a.h>
//前面可以采用ARR
注意,这里必须采用static润色,不然多个文件包含导致校对会出现重复定义的严重错误。有兴趣的可以试著一下。
const润色的表达式是或者说的黎贞吗?
采用const润色之后的表达式真的是完全的黎贞吗?看下面这个例子:
#include <stdio.h>
int main(void)
{
const int a = 2018;
int *p = &a;
*p = 2019;
printf(“%d\n”,a);
return 0;
}
运行结果:
2019
可以看到,他们透过另外定义两个操作方式符表达式,将被const润色的a的值发生改变了。所以他们不禁要问,const究竟做了什么呢?它润色的表达式是或者说象征意义上的黎贞吗?为什么它润色的表达式的值仍然可以发生改变?
#include<stdio.h>
int main(void)
{
int a = 2019;
//const int a = 2019;
printf(“%d\n”,a);
return 0;
}
无const润色,汇编代码:
.LC0:
.string “%d\n”
main:
push rbp
mov rbp, rsp
sub rsp, 16
mov DWORD PTR [rbp-4], 2019
mov eax, DWORD PTR [rbp-4]
mov esi, eax
mov edi, OFFSET FLAT:.LC0
mov eax, 0
call printf
mov eax, 0
leave
ret
有const润色,汇编代码:
.LC0:
.string “%d\n”
main:
push rbp
mov rbp, rsp
sub rsp, 16
mov DWORD PTR [rbp-4], 2019
mov eax, DWORD PTR [rbp-4]
mov esi, eax
mov edi, OFFSET FLAT:.LC0
mov eax, 0
call printf
mov eax, 0
leave
ret
他们发现,并没任何差异!当然这两个例子并不能表明所有的难题。但是他们要晓得的是,constURL告诉了校对器,它润色的表达式不能被发生改变,假如代码中发现有类似发生改变该表达式的操作方式,所以校对器就会捕捉这个严重错误。
所以它在前述中的象征意义之一是什么呢?帮助程序员提前发现难题,避免不该修正的值被意外地修正,但是无法完全保证不被修正!比如他们可以透过对操作方式符展开强转:
#include<stdio.h>
void myPrint(const char *str);
void myPrint(const char *str)
{
char *b = (char *)str;
b[0] = H;
printf(“my print:%s\n”,b);
}
int main(void)
{
char str[] = “hello world”;
myPrint(str);
return 0;
}
运行结果:
my print:Hello world
也就是说,constURL是给校对器用的,帮助程序员提早发现可能存在的难题。
但是前述中永远不要写这样的代码!
总结
如是说了这么多,关键点如下:
constURL让校对器帮助他们发现表达式不该被修正却被意外修正的严重错误。constURL润色的表达式并非或者说象征意义完完全全的黎贞。对于不该被修正的入参,应该用const润色,这是const采用的常见姿势。const润色的表达式根本无法正常表达式一次。不要企图将const数据的地址赋给一般操作方式符。不要忽略校对器的警告,除非你很清楚在做什么。虽然可以透过某种不正规途径修正const润色的表达式,但是永远不要这么做。思考
与#define相比,const有什资源。欢迎一起交流学习,一起修炼计算机“内功”,知其然,更知其所以然。