restrict关键字用于告诉编译器,对象已经被指针所引用,不能通过除该指针外所有其他直接或间接的方式修改该对象的内容(并非强制性的规定,即用了其他指针访问该内存空间也不会报错)。注意,这是一个C语言的优化关键字,开发者需要自己在编码的时候注意只能使用该指针访问特定的内存空间,并且多个指针指向的空间也不能重叠,以便于编译器后期的优化。使用该关键字时一定要额外小心,不然会出现意想不到的BUG。
以下源码编译为汇编代码的时候使用了海思3519AV100的编译链arm-himix200-linux-,且加了-O1优化选项。
(1)没加Restrict的代码
源码:
#include <stdio.h>
void test(int* a, int* b)
{
(*a)++;
(*b)++;
(*a) += 3;
(*b)++;
}
int main(int argc, char** args)
{
int val1 = 10, val2 = 11;
test(&val1, &val2);
printf("Val1:%d Val2:%d\n", val1, val2);
return 0;
}
汇编代码:
test:
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, uses_anonymous_args = 0
@ link register save eliminated.
//(*a)++
ldr r3, [r0]
add r3, r3, #1
str r3, [r0]
//(*b)++
ldr r3, [r1]
add r3, r3, #1
str r3, [r1]
//(*a) += 3
ldr r3, [r0]
add r3, r3, #3
str r3, [r0]
//(*b)++
ldr r3, [r1]
add r3, r3, #1
str r3, [r1]
bx lr
.size test, .-test
.align 2
.global main
.syntax unified
.arm
.fpu softvfp
.type main, %function
(2)加了Restrict
源码:
#include <stdio.h>
void test(int* restrict a, int* restrict b)
{
(*a)++;
(*b)++;
(*a) += 3;
(*b)++;
}
int main(int argc, char** args)
{
int val1 = 10, val2 = 11;
test(&val1, &val2);
printf("Val1:%d Val2:%d\n", val1, val2);
return 0;
}
汇编代码:
test:
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, uses_anonymous_args = 0
@ link register save eliminated.
ldr r3, [r1]
ldr r2, [r0]
//可以看到这里进行优化,变成了(*a) += 4;
add r2, r2, #4
str r2, [r0]
//这里也进行了优化,变成了(*b) += 2;
add r3, r3, #2
str r3, [r1]
bx lr
.size test, .-test
.align 2
.global main
.syntax unified
.arm
.fpu softvfp
.type main, %function
还有一则例子如下,该例子中加了restrict关键字之后产生的返回值将是个错误值,因为该代码给test函数传入了两个指向同一块内存的指针(都是val1的指针),这样违反了restrict关键字的规则,但是编译的时候并不会报错,所以说restrict关键字不是强制性规定的关键字,它需要开发者自己注意其规则。
(1)没加restrict
源码:
#include <stdio.h>
int test(int* a, int* b)
{
*a = 8;
*b = 9;
return *a + *b;
}
int main(int argc, char** args)
{
int val1 = 10, val2 = 11;
val2 = test(&val1, &val1);
printf("Val1:%d Val2:%d\n", val1, val2);
return 0;
}
汇编代码:
test:
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, uses_anonymous_args = 0
@ link register save eliminated.
//这里r0和r1分别存放了指针a和b
//*a = 8和*b = 9
mov r3, #8
str r3, [r0]
mov r3, #9
str r3, [r1]
ldr r0, [r0]
//*a + *b,注意这里仍会从寄存器取值进行操作,这和加了restrict不一样
add r0, r0, r3
bx lr
.size test, .-test
.align 2
.global main
.syntax unified
.arm
.fpu softvfp
.type main, %function
(2)加了restrict
源码:
#include <stdio.h>
int test(int* restrict a, int* restrict b)
{
*a = 8;
*b = 9;
return *a + *b;
}
int main(int argc, char** args)
{
int val1 = 10, val2 = 11;
val2 = test(&val1, &val1);
printf("Val1:%d Val2:%d\n", val1, val2);
return 0;
}
汇编代码:
test:
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, uses_anonymous_args = 0
@ link register save eliminated.
//*a = 8和*b = 9,这部分和没加restrict的一样
mov r3, #8
str r3, [r0]
mov r3, #9
str r3, [r1]
/*这里直接优化成返回立即数17,不再从内存或寄存器中取值进行计算。因为有restrict关键字的修
饰,编译器可以大胆地进行代码优化,但有时候这种优化也会带来致命的后果,因此使用该关键字
时,程序员一定要小心谨慎*/
mov r0, #17
bx lr
.size test, .-test
.align 2
.global main
.syntax unified
.arm
.fpu softvfp
.type main, %function