const关键字到底该怎么用

2023-06-27 0 857

序言

他们都晓得采用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有什资源。欢迎一起交流学习,一起修炼计算机“内功”,知其然,更知其所以然。

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务