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

时间:2009-05-07 05:09:06

标签: c pointers c99 restrict-qualifier

我对restrict有一个大致的了解,但我希望澄清一些细节。我有一个函数从一个缓冲区读取一个以null结尾的字符串,并在另一个缓冲区中写出一个URL编码的版本。该函数具有此签名(当前没有restrict):

char const *StringUrlEncode(char const *unencoded, 
                            char *encoded,
                            char *encodedEnd);

unencoded是我的以null结尾的源字符串。目标缓冲区由encodedencodedEnd表示,其中encoded指向缓冲区中的第一个charencodedEnd指向第一个char 缓冲区之后,即函数将写入char,但不包括 encodedEnd指向的位置 - 这是您的基本{{1如果你熟悉C ++ STL约定,那么/ begin迭代器对。

如果我将end添加到此函数,它是否应仅应用于前两个参数:

restrict

或者通过将它添加到所有三个参数中,我有什么好处?

我可以看到,输入和输出缓冲区char const *StringUrlEncode(char const *restrict unencoded, char *restrict encoded, char *encodedEnd); 有助于编译器知道它们不重叠。但由于最后一个参数restrict仅用于标记输出缓冲区的结尾,我认为encodedEnd对编译器没有任何帮助(尽管我假设它)除了在函数声明中添加不必要的噪音之外,不会受到伤害。

3 个答案:

答案 0 :(得分:12)

尝试Mike Acton的文章here。限制是可怕的,因为不使用它的性能影响和不正确使用它的后果。

在你的情况下,听起来你可以安全地对所有三个指针应用restrict,因为没有别名相同的内存区域。但是,在第三个指针上使用它几乎没有性能优势。

答案 1 :(得分:7)

在这种特殊情况下, encodedEnd 是否受限制无关紧要;你承诺编译器没有人将未编码编码别名,因此读写不会相互干扰。

在这种情况下限制很重要的真正原因是没有它,编译器就不能知道通过编码写入不会影响通过未编码的读取。例如,如果

encoded == unencoded+1

然后每次写入编码都会影响 unncoded 的每次后续读取,因此编译器无法在写入完成之前调度加载。限制承诺编译器,两个指针不会影响相同的内存,因此它可以提前调度负载,以避免管道停滞。

答案 2 :(得分:4)

我认为你是对的,它不会受到伤害。你的循环指针(称之为p)将在循环结束时等于encodedEnd。但是在循环之后不需要访问任何东西(来自p或encodedEnd),所以这应该不是问题。我认为它也不会有所帮助,因为没有任何东西可以从encodedEnd写入或读取,因此无法优化。

但我同意你的前两个限制应该真的有帮助。