IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C/C++中的restrict关键字 -> 正文阅读

[C++知识库]C/C++中的restrict关键字

restrict用于限定和约束指针,表示这个指针只访问这块内存的唯一方式,也就是告诉编译器,这块内存中的内容的操作都只会通过这个指针,而不会通过其他变量或者指针。这个指针有两个作用,一个是告诉编译器,编译器一旦获得了这个信息,那么就可以放心大胆地对这个进行优化。另一个作用是告诉程序员,这段内存只能通过这个指针访问。

作用一: 告诉编译器,编译器可以根据这个大胆做优化

int * restrict?ptr = (int *) malloc(sizeof(int));

告诉编译器,申请的这块内存,只会通过ptr这个指针来访问。那么如果有如下函数:

void test()
{
    int a = 0;
    int *tmp = &a;
    int * restrict ptr = (int*) malloc(10);
    *ptr = 0;
    *ptr += 2;
    *tmp += 1;
    *ptr += 3;
    *tmp += 2;
    a += 3;
}

对于ptr指针,编译器会优化成*ptr += (2+3);一条语句。但是tmp这个指针就不能优化成*tmp += 3,因为可能这个地址会通过a来修改。

需要注意的是,这个只是约定而已,如果你加了这个restrict限定,那么需要有程序员保证这一规则的成立,也就是说,即使你用一个新的指针指向ptr,然后通过这个指针修改内容,编译器也不会报错。但是可能就没有优化效果了。(未看汇编证实,后续证实)

作用二:告诉程序员,这段内存需要满足restrict规则

C库中有两个函数可以从一个位置把字节复制到另一个位置。在C99标准下,它们的原型如下:

void * memcpy(void * restrict s1, const void * restrict s2,?size_t?n);

void * memmove(void * s1, const void * s2, size_t n);

这两个函数均从s2指向的位置复制n字节数据到s1指向的位置,且均返回s1的值。两者之间的差别由关键字restrict造成,即memcpy函数内部可以假定两个内存区域没有重叠,但是需要使用者来保证,如果没有按照规则,则内部的实现如果没有考虑重叠的情况,就可能出问题。memmove()函数则不做这个假定,因此,复制过程类似于首先将所有字节复制到一个临时缓冲区,然后再复制到最终目的地。同样,编译器并不会对这个做检测,你告诉编译器什么,编译器就相信什么了。

对于这个问题,我们举个简单例子:

void test()
{
    char *ptr = (char*)malloc(10);
    char *tmp = ptr + 3;
    memset(ptr, '\0', 10);
    snprintf(ptr, 10, "%s", "HelloWorld");
    memcpy(tmp, ptr, 5);
}

如上面的代码,tmp初始指向字符‘l’,按照本意,我们是想把从ptr开始的5个字符“Hello”复制到从tmp开始的地址上。那么如果memcpy没有考虑地址重叠的话,它会从ptr开始把字符一个一个拷贝到tmp地址上。那么你就会发现,当把第一个字符“H”拷贝到tmp指向'l'的位置的时候,被拷贝的5个字符已经变成“HelHo"了,也就是改dst的同时,也改到了src了。那这样起来肯定会违背我们的本意,但是这个不是memcpy的锅,人家已经通过restrict告诉你s2这块地址只有限定在只能通过s2指针来访问才能保证没问题,是你自己没按照函数规则来。

这也告诉我们,在设计memcpy的时候,需要考虑这种情况。解决办法如下,当修改dst也有可能改到src的情况下,可以把src和dst均加上要拷贝的size,然后从尾巴开始逐一字符拷贝,这样就不会有重叠了。

参考:https://baike.baidu.com/item/restrict/7384270?fr=aladdin

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-02 10:37:50  更:2021-08-02 10:38:56 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 5:17:46-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码