龙空技术网

C语言的灵魂指针,配合这个新增的关键字,能够生成更高效的程序

IT刘小虎 286

前言:

现时你们对“c语言关键字可以自己创建吗”大约比较关怀,我们都需要剖析一些“c语言关键字可以自己创建吗”的相关资讯。那么小编同时在网上网罗了一些关于“c语言关键字可以自己创建吗””的相关知识,希望我们能喜欢,兄弟们快快来学习一下吧!

正如我前面的文章提到的,C语言虽然已经比较成熟,但是近些年来也是有所发展的——比如增加了许多新特性。遗憾的是,可能因为C语言程序员的工资比不过互联网程序员,国内很多教材比较老旧,几乎不涉及近些年来C语言新增的新特性。

C语言程序员的工资比不过互联网程序员

事实上,目前大多数平台已经至少支持 C99 标准,而 C99 中新增的一些特性或者关键字的确非常好用,能够大大提升C语言程序的开发效率,以及增加代码可读性。

restrict 关键字

例如,C99 中新增了 restrict 关键字,它能够帮助编译器优化C语言代码,生成效率更高的程序。

确切来说,restrict 是为C语言指针服务的关键字,程序员可以通过 restrict 通知编译器指针索引内存的一些特征,便于编译器有选择的优化代码,生成高效程序。

restrict 关键字修饰指针时,用于通知编译器只有该指针以及该指针的派生值(例如指针+1)才用于访问指向的对象,别的指针不会和该指针一样指向相同的对象。这有助于编译器执行优化,稍后读者可通过一个例子看到这一点。

这有助于编译器执行优化

如果编译器不能确定上面这样的特征,将不敢执行优化,否则可能导致程序出现“未定义”的行为。原则上来说,合理的使用 restrict 关键字,可以让最终的C语言程序提升相当多的性能。

实例

接下里,本文将以两个简单实例讨论 restrict 关键字的作用,请看下面这段C语言代码:

void updatePtrs(size_t *ptrA, size_t *ptrB, size_t *val){ *ptrA += *val; *ptrB += *val;}

代码很简单,无非就是将前面 ptrA 和 ptrB 指向的值加上 val 指向的值。但是由于 ptrA,ptrB,val 三个指针可能指向同一块内存,所以编译器不能最大程度执行优化,因此最终生成的指令可能是下面这样的:

load R1 ← *val ;从地址 val 处加载值到寄存器 R1 里load R2 ← *ptrAadd R2 += R1 ;执行加操作,结果放在寄存器 R2 里store R2 → *ptrA ;将寄存器 R2 中的值传递到地址 ptrA 处load R2 ← *ptrBload R1 ← *valadd R2 += R1store R2 → *ptrB

最终生成的指令

不过,如果使用了 restrict 关键字修饰三个指针,情况就不同了。修改后的 updatePtrs() 函数的C语言原型如下,请看:

void updatePtrs(size_t *restrict ptrA,  size_t *restrict ptrB,  size_t *restrict val);

应注意,程序员使用 restrict 关键字修饰指针时,应自己确保三个指针指向的内存没有指向同一块内存。因为编译器此时就是这么认为的,因此它可以重新安排代码,执行优化,最终生成下面这样的指令:

load R1 ← *valload R2 ← *ptrAload R3 ← *ptrBadd R2 += R1add R3 += R1store R2 → *ptrAstore R3 → *ptrB

执行效率更高的程序

显然,这种情况下,程序只需加载 val 指向的值一次。此外,由于编译器可以更自由地优化C语言代码,因此编译器可以生成执行效率更高的程序。

从上述生成的指令可以看出,存储操作都是在加载操作之后进行的,这确保了处理器不必在代码中间阻塞以等待存储操作完成。

最后

应该注意,在不同的机器上编译C语言程序时,实际生成的指令可能不同。但是 restrict 关键字的作用是相同的——它通知编译器可以更加自由的优化代码,以提升最终C语言程序的效率。

点个赞再走吧

欢迎在评论区一起讨论,质疑。文章都是手打原创,每天最浅显的介绍C语言、linux等嵌入式开发,喜欢我的文章就关注一波吧,可以看到最新更新和之前的文章哦。

未经许可,禁止转载。

标签: #c语言关键字可以自己创建吗