浅谈C语言的restrict关键字

 

 

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

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值