8. restrict 关键字

restrict 关键字 是 C 语言的 C99 标准中引入的一个关键字,它只能修饰指针的关键字。它用于向编译器提供承诺,此指针只能由这一个指针来操作这段内存,没有其它指针来指向这段内存。以便编译器使用更有力的优化策略对这段代码进行优化。

语法

数据类型 * restrict 指针变量名;

示例:

例如在 Linux系统下的 C 语言库函数中的 strcat 函数的定义如下:

char *strcat(char *restrict dst, const char *restrict src);

我们编写如下程序:

// filename: restrict.c
#include <stdio.h>
#include <string.h>

int main(int argc, char * argv[]) {
    char str1[100] = "hello ";
    char str2[100] = "world!";

      // 不会有restrict 警告
    strcat(str1, str2);
    printf("str1: %s\n", str1);

    // 以下 GCC 编译器会有restrict 警告 结果也会不确定。
    strcat(str1, str1);   // strcat 的形式参数的两个指针指向和同一个地址。
    printf("str1: %s\n", str1);

    return 0;
}

编译和运行结果如下:

weimingze@mzstudio:~$ gcc -o restrict restrict.c -Wall
restrict.c: In function ‘main’:
restrict.c:14:12: warning: passing argument 1 to ‘restrict’-qualified parameter aliases with argument 2 [-Wrestrict]
   14 |     strcat(str1, str1);   // strcat 的形式参数的两个指针指向和同一个地址。
      |            ^~~~  ~~~~
weimingze@mzstudio:~$ ./restrict
str1: hello world!
str1: hello world!hello world!

重上面示例可以看出。由于 strcat 进行了优化。我们使用 strcat(str1, str2); 进行操作相对是比较安全的,因为两块内存是不同的区域。当我们使用 strcat(str1, str1); 对同一个地址的数据进行复制时,编译器会给出警告。

注意事项

  1. restrict 是程序编写人员给编译器的承诺。编译器并不会检查此指针是否有别名。
  2. 违反 restrict 的承诺,程序执行结果可能是未定义行为。