-- TOC --
C99引入了restrict关键词,用来修饰指针。
概括的说,关键字restrict只用于限定指针。restrict告诉编译器,所有修改该指针所指向内容的操作全部都是基于(base on)该指针的,即不存在其它进行修改操作的途径;这样的效果是帮助编译器进行更好的代码优化,生成更有效率的汇编代码。
#include <stdio.h>
// __restrict is also OK
int func1(int *restrict a, int *restrict b){
*a = 1;
*b = 2;
return *a + *b;
}
int func2(int *a, int *b){
*a = 1;
*b = 2;
return *a + *b;
}
int main(void){
int a,b;
func1(&a, &b);
func2(&a, &b);
return 0;
}
我们来看看func1和func2在-O3
时的汇编:
$ gcc -c test.c -O3
[xinlin@likecat test]$ objdump -d test.o
test.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <func1>:
0: c7 07 01 00 00 00 movl $0x1,(%rdi)
6: b8 03 00 00 00 mov $0x3,%eax
b: c7 06 02 00 00 00 movl $0x2,(%rsi)
11: c3 ret
0000000000000020 <func2>:
20: c7 07 01 00 00 00 movl $0x1,(%rdi)
26: c7 06 02 00 00 00 movl $0x2,(%rsi)
2c: 8b 07 mov (%rdi),%eax
2e: 83 c0 02 add $0x2,%eax
31: c3 ret
Disassembly of section .text.startup:
0000000000000000 <main>:
0: 31 c0 xor %eax,%eax
2: c3 ret
由于func1的两个参数有restrict修饰,编译器对其代码进行了优化。编译器通过restrict修饰了解到,此时,能够修改*a
指向内存的内容的,只有这里的a
指针,因此,不管给*a
赋值为何,这个值都不会被其它指针在其它地方修改,因此后面在做加法的时候,就可以不用再访问内存了(func2中的mov (%rdi),%eax
指令,读取内容的值,存入eax寄存器)。
但,什么时候可以用restrict修饰指针,需要程序员明察秋毫!
memcpy的两个入参指针,都有restrict修饰,而memmove就没有。(参考memcpy和memmove的异同)
gcc和g++都可识别__restrict
,-O3
时都有优化效果,C/C++混编的时候,建议使用。
本文链接:https://cs.pynote.net/sf/c/202301161/
-- EOF --
-- MORE --