Tag: 限制限定符

将限定的限制指针传递给函数?

限制合格的指针被解释为有一个规则:指针访问并在任何地方修改的任何对象只能由指针访问。 所以以下不起作用吧? void agSum( int * restrict x, int n ){ for(int i=0; i<n-1; i++) x[i+1] += x[i]; } int SumAndFree( int * restrict y, int n ){ agSum(y); printf("%i",y[n-1]); free(y); } 所以,我猜这是无效的,因为y [n-1]被修改到某个地方,不能直接从限制指针y访问,而是由y读取。 如果这是正确的,当输入指针限制合格时,如何调用函数? 似乎该function在不违反限制规则的情况下无法执行任何操作。 释放限制指针是否是另一种违规行为? 我想这是一种修改。 提前致谢!

我使用restrict限定符时出错

当我编译以下程序时,我得到错误: gcc tester.c -o tester tester.c: In function ‘main’: tester.c:7:17: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘ptr_X’ tester.c:7:17: error: ‘ptr_X’ undeclared (first use in this function) tester.c:7:17: note: each undeclared identifier is reported only once for each function it appears in tester.c:10:17: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘ptr_Y’ […]

使用数组限制?

有没有办法告诉C99编译器我要访问给定数组的唯一方法是使用myarray [index]? 说这样的话: int heavy_calcualtions(float* restrict range1, float* restrict range2) { float __I promise I won’t alias this__ tmpvalues[1000] = {0}; …. heavy calculations using range1, range2 and tmpvalues; …. } 通过使用restrict我承诺我不会为range1和range2设置别名但是如何为我的函数内部声明的数组做同样的事情?

重叠指针,类型的限制限定符的粒度

restrict的全部要点是承诺通过一个指针访问不要别名。 也就是说,有些例子表明重叠的内存地址不会暗示别名。 例如: int* arr_ptr0 = &arr[0]; int* arr_ptr1 = &arr[1]; for (int i=0;i<10;++i) { *arr_ptr0 = *arr_ptr1; arr_ptr0 += 2; arr_ptr1 += 2; } 问题是,这些指针确实指向重叠的内存! 对于这个特定的例子,像这样的指南说,例如: 这是有效的。 。 。 指向同一个数组对象,前提是通过其中一个指针访问的元素范围与通过另一个指针访问的元素范围不重叠。 我的问题是: 什么粒度是“元素”? 例如,假设我有一个struct Foo类型的数组。 我是否真的需要确保我不会访问相同范围的元素( Foo ),即使我访问的部分是不相交的? 这是一个简单的标量示例: struct Foo { int i; float f; }; void f(struct Foo*restrict foo0, struct Foo*restrict foo1) { […]

何时使用限制,何时不使用

我对restrict有一般性的了解,但我希望澄清一些细节。 我有一个函数从一个缓冲区读取一个以null结尾的字符串,并在另一个缓冲区中写出一个URL编码的版本。 该函数具有此签名(目前没有restrict ): char const *StringUrlEncode(char const *unencoded, char *encoded, char *encodedEnd); unencoded是我的以null结尾的源字符串。 目标缓冲区由encoded和encodedEnd表示,其中encoded指向缓冲区中的第一个char , encodedEnd指向缓冲区后的第一个char,即函数将写入char ,但不包括 encodedEnd指向的位置 – – 如果您熟悉C ++ STL约定,这是您的基本begin / end迭代器对。 如果我将restrict添加到此函数,它是否应仅应用于前两个参数: char const *StringUrlEncode(char const *restrict unencoded, char *restrict encoded, char *encodedEnd); 或者通过将它添加到所有三个参数中我是否有一些好处? 我可以看到,使输入和输出缓冲区restrict有助于编译器知道它们不重叠。 但是由于最后一个参数encodedEnd仅用于标记输出缓冲区的结尾,我认为restrict对这里的编译器没有任何帮助(虽然我认为它不会伤害,除了添加function声明中不必要的噪音)。

通过示例了解限制限定符

restrict关键字的行为在C99中由6.7.3.1定义: 设D是普通标识符的声明,它提供了一种将对象P指定为类型T的限制限定指针的方法。 如果D出现在块内并且没有存储类extern,则让B表示该块。 如果D出现在函数定义的参数声明列表中,则让B表示关联的块。 否则,让B表示main的块(或者在独立环境中的程序启动时调用任何函数的块)。 在下文中,指针表达式E被称为基于对象P if(在评估E之前执行B中的某个序列点)修改P以指向其先前指向的数组对象的副本将改变E.119的值)注意”based”仅针对具有指针类型的表达式定义。 在每次执行B期间,让L为任何具有&L基于P的左值。如果L用于访问它指定的对象X的值,并且X也被修改(通过任何方式),则以下要求适用:T不应该是const限定的。 用于访问X值的每个其他左值也应具有基于P的地址。出于本子条款的目的,每次修改X的访问也应被视为修改P. 如果P被赋予指针表达式E的值,该指针表达式E基于与块B2相关联的另一个受限指针对象P2,则B2的执行应在执行B之前开始,或者B2的执行应在该执行之前结束。分配。 如果不满足这些要求,则行为未定义。 就像其他人一样,我很难理解这个定义的所有复杂性。 作为这个问题的答案,我希望看到第4段中每个要求违反要求的一些好例子。 本文: http://web.archive.org/web/20120225055041/http://developers.sun.com/solaris/articles/cc_restrict.html 在“编译器可能假设……”方面做得很好。 扩展该模式并将编译器可以做出的假设以及它们如何无法保持,每个示例都很棒。

如果指针已经标记为const,是否限制C中的帮助?

只是想知道:当我向指针添加restrict时,我告诉编译器指针不是另一个指针的别名。 我们假设我有一个类似的函数: // Constructed example void foo (float* result, const float* a, const float* b, const size_t size) { for (size_t i = 0; i < size; ++i) { result [i] = a [0] * b [i]; } } 如果编译器必须假设result可能与a重叠,则每次都必须重新获取。 但是,作为a标记为const ,编译器也可以假设a是固定的,因此一次获取它就可以了。 问题是,在这种情况下,使用restrict的推荐方法是什么? 我当然不希望编译器每次都重新获取,但我找不到有关如何在这里使用restrict好信息。

在某些情况下,您可以使用限制指针来访问同一个对象吗?

大多数限制的定义都说它是程序员对编译器的承诺,在指针的生命周期中,指针是访问对象的唯一方式。 这允许编译器优化输出,因为它知道它只能由一个指针访问,因此只能由它来改变。 如果我理解正确通常意味着程序不必重新加载指针指向的值。 如果这是正确的,那么当restrict关键字应该可用时应该有一些例外,即使它违背了应该如何使用它的意图。 我想到的一件事是指针指向的数据在指针的生命周期内从未实际发生过变化。 在这种情况下,即使指针指向同一位置,也不需要重新加载数据,因为它们在指针的生命周期中不会改变。 例如: int max(int *restrict a, int *restrict b) { return((*a > *b) ? *a : *b); } int main(void) { int num = 3; int max = max(&num, &num); } 这是对限制的有效使用,即使它与它应该如何使用相反吗? 使用像这样的restrict关键字会导致未定义的行为吗?