restrict关键字(暗示编译器,某个指针指向的空间,只能从该指针访问)
2017-03-11 09:29
267 查看
我们希望某个对象(内存空间)不被修改的通常做法是什么?声明该空间的const类型,但是这样真的可以吗?是不是的,由于const空间对象的指针是可以付给一个非const值指针的。所以这仍然无法不让该空间被修改。
虽然,编译器会报警告“ 警告:初始化丢弃了指针目标类型的限定”,这个意思是,b失去了对目标对象的const的限定。但是通过,并且,可以通过指针b更改它们共同指向的空间。
这种写法和上面的效果一样,却连警告都不报,这就可以看到C语言类型转换的功能有多大,并且有多危险。当我们将a的地址转换成int类型的时候,编译器不会认为这是一个严重的事情(因为int类型并不能访问内存空间),之后再从int类型转换到int *类型,这个时候,编译器也很难确定这是否会出现不安全的地方。所以,这样一做,就骗过了C编译器。而前面的方法中,编译器明显看到两个指针之间的赋值初始化,是有不安全的地方的(丢掉了const的对象设定),所以发出警告。
不过,一句话,const是无法保证某个对象不被更改的。所以C99提出了一个restrict关键字。它是修饰指针的,表达出的意思是,对该指针指向的空间的访问,只能从这个指针进入。这样,如果该关键字在加上restrict,就会达到锁定该空间。当然,restrict不一定只是为了建立一个完全常态的空间,它的本意是限制该空间只能通过该指针进行访问。
restrict pointer是c99新标准提出的一个很著名的概念叫着——受限指针。这种指针的声明是为了,编译达到更好的优化,它暗示编译器,某个指针指向的空间,只能从该指针访问。但是这种暗示却是对程序员的要求,而编译器只是在这种暗示的基础上作一些优化。
restrict只可以用在指针身上。如果一个指针被restrict修饰,那么就在它(这个指针)和它所指向的对象之间建立了一种特殊的联系──只能用这个指针或者这个指针的表达式来访问这个对象的值。
一个指针指向一个内存地址。同一块内存可以由多个指针来访问并在程序运行时修改它(这块内存)。restrict告诉编译器,如果一块由一个被restrict修饰的指针所指向的内存被修改了,那么没有其它的指针可以来访问这块内存。编译器可能会选择一种方式来优化代码中调用被restrict修饰的指针的部分,这可能导致错误发生。程序员有责任来确保正确地按照他们所设想的来使用被restrict修饰的指针,否则的话,可能会发生意想不到的结果。
C库中的例子
这两个函数均从s2指向的位置复制n字节数据到s1指向的位置,且均返回s1的值。两者之间的差别由关键字restrict造成,即memcpy()可以假定两个内存区域没有重叠。memmove()函数则不做这个假定,因此,复制过程类似于首先将所有字节复制到一个临时缓冲区,然后再复制到最终目的地。如果两个区域存在重叠时使用memcpy()会怎样?其行为是不可预知的,既可以正常工作,也可能失败。在不应该使用memcpy()时,编译器不会禁止使用memcpy()。因此,使用memcpy()时,您必须确保没有重叠区域。这是程序员的任务的一部分。关键字restrict有两个读者。一个是编译器,它告诉编译器可以自由地做一些有关优化的假定。另一个读者是用户,他告诉用户仅使用满足restrict要求的参数。一般,编译器无法检查您是否遵循了这一限制,如果您蔑视它也就是在让自己冒险。
const int a=10; int * b=&a;
虽然,编译器会报警告“ 警告:初始化丢弃了指针目标类型的限定”,这个意思是,b失去了对目标对象的const的限定。但是通过,并且,可以通过指针b更改它们共同指向的空间。
const int a=10; int b=(int)&a; int * c=(int *)b;
这种写法和上面的效果一样,却连警告都不报,这就可以看到C语言类型转换的功能有多大,并且有多危险。当我们将a的地址转换成int类型的时候,编译器不会认为这是一个严重的事情(因为int类型并不能访问内存空间),之后再从int类型转换到int *类型,这个时候,编译器也很难确定这是否会出现不安全的地方。所以,这样一做,就骗过了C编译器。而前面的方法中,编译器明显看到两个指针之间的赋值初始化,是有不安全的地方的(丢掉了const的对象设定),所以发出警告。
不过,一句话,const是无法保证某个对象不被更改的。所以C99提出了一个restrict关键字。它是修饰指针的,表达出的意思是,对该指针指向的空间的访问,只能从这个指针进入。这样,如果该关键字在加上restrict,就会达到锁定该空间。当然,restrict不一定只是为了建立一个完全常态的空间,它的本意是限制该空间只能通过该指针进行访问。
restrict pointer是c99新标准提出的一个很著名的概念叫着——受限指针。这种指针的声明是为了,编译达到更好的优化,它暗示编译器,某个指针指向的空间,只能从该指针访问。但是这种暗示却是对程序员的要求,而编译器只是在这种暗示的基础上作一些优化。
restrict只可以用在指针身上。如果一个指针被restrict修饰,那么就在它(这个指针)和它所指向的对象之间建立了一种特殊的联系──只能用这个指针或者这个指针的表达式来访问这个对象的值。
一个指针指向一个内存地址。同一块内存可以由多个指针来访问并在程序运行时修改它(这块内存)。restrict告诉编译器,如果一块由一个被restrict修饰的指针所指向的内存被修改了,那么没有其它的指针可以来访问这块内存。编译器可能会选择一种方式来优化代码中调用被restrict修饰的指针的部分,这可能导致错误发生。程序员有责任来确保正确地按照他们所设想的来使用被restrict修饰的指针,否则的话,可能会发生意想不到的结果。
C库中的例子
C库中有两个函数可以从一个位置把字节复制到另一个位置。在C99标准下,它们的原型如下:
void * memcpy(void * restrict s1, const void * restrict s2, size_t n); void * memove(void * s1, const void * s2, size_t n);
这两个函数均从s2指向的位置复制n字节数据到s1指向的位置,且均返回s1的值。两者之间的差别由关键字restrict造成,即memcpy()可以假定两个内存区域没有重叠。memmove()函数则不做这个假定,因此,复制过程类似于首先将所有字节复制到一个临时缓冲区,然后再复制到最终目的地。如果两个区域存在重叠时使用memcpy()会怎样?其行为是不可预知的,既可以正常工作,也可能失败。在不应该使用memcpy()时,编译器不会禁止使用memcpy()。因此,使用memcpy()时,您必须确保没有重叠区域。这是程序员的任务的一部分。关键字restrict有两个读者。一个是编译器,它告诉编译器可以自由地做一些有关优化的假定。另一个读者是用户,他告诉用户仅使用满足restrict要求的参数。一般,编译器无法检查您是否遵循了这一限制,如果您蔑视它也就是在让自己冒险。
相关文章推荐
- 获取数组和指针指向空间大小
- new、delete、指向连续空间的指针、数组、空间释放、空间申请[C++][内存管理]
- 对用父类指针(或引用)指向父类对象和子类对象时,从而用父类指针或者引用访问成员时的深刻理解;
- 指针数组(指向指针的指针)空间的释放
- 指针指向紧邻对象所占空间的下一个位置
- c/c++中怎样为指向指针的指针分配空间
- 获取指针指向空间大小
- 用对象和用指向基类的指针访问成员函数
- 访问元素:指向数组的指针与指向指针的指针
- “返回指向栈空间的指针”的错误
- 常对象只能由常指针访问
- 习题 8.19(1) 编写一个函数new,对n个字符开辟连续的存储空间,此函数应返回一个指针(地址),指向字符串开始的空间。new(n)表示分配n个字节的内存空间。
- 面向对象三大特征,super关键字,以及父类引用指向子类对象。访问权限的大小。
- 【c语言】编写一个函数new,对n个字符开辟连续的存储空间,此函数应返回一个指针(地址),指向字符串开始的空间
- Objective-C定义一个指向函数的指针、直接访问成员变量
- 题目:将二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向
- delete 指针之后 ,只是释放了指针指向的内存空间,指针不会自动置为NULL,还有delete 遇到指针为NULL时不会调用析构函数
- 条款 30: 避免这样的成员函数:其返回值是指向成员的非 const 指针或引用, 但成员的访问级比这个函数要低
- new、delete、指向连续空间的指针、数组、空间释放、空间申请[C++][内存管理]
- 牛客原题 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。