我对restrict
有一个大致的了解,但我希望澄清一些细节。我有一个函数从一个缓冲区读取一个以null结尾的字符串,并在另一个缓冲区中写出一个URL编码的版本。该函数具有此签名(当前没有restrict
):
char const *StringUrlEncode(char const *unencoded,
char *encoded,
char *encodedEnd);
unencoded
是我的以null结尾的源字符串。目标缓冲区由encoded
和encodedEnd
表示,其中encoded
指向缓冲区中的第一个char
,encodedEnd
指向第一个char 在缓冲区之后,即函数将写入char
,但不包括 encodedEnd
指向的位置 - 这是您的基本{{1如果你熟悉C ++ STL约定,那么/ begin
迭代器对。
如果我将end
添加到此函数,它是否应仅应用于前两个参数:
restrict
或者通过将它添加到所有三个参数中,我有什么好处?
我可以看到,输入和输出缓冲区char const *StringUrlEncode(char const *restrict unencoded,
char *restrict encoded,
char *encodedEnd);
有助于编译器知道它们不重叠。但由于最后一个参数restrict
仅用于标记输出缓冲区的结尾,我认为encodedEnd
对编译器没有任何帮助(尽管我假设它)除了在函数声明中添加不必要的噪音之外,不会受到伤害。
答案 0 :(得分:12)
尝试Mike Acton的文章here。限制是可怕的,因为不使用它的性能影响和不正确使用它的后果。
在你的情况下,听起来你可以安全地对所有三个指针应用restrict,因为没有别名相同的内存区域。但是,在第三个指针上使用它几乎没有性能优势。
答案 1 :(得分:7)
在这种特殊情况下, encodedEnd 是否受限制无关紧要;你承诺编译器没有人将未编码和编码别名,因此读写不会相互干扰。
在这种情况下限制很重要的真正原因是没有它,编译器就不能知道通过编码写入不会影响通过未编码的读取。例如,如果
encoded == unencoded+1
然后每次写入编码都会影响 unncoded 的每次后续读取,因此编译器无法在写入完成之前调度加载。限制承诺编译器,两个指针不会影响相同的内存,因此它可以提前调度负载,以避免管道停滞。
答案 2 :(得分:4)
我认为你是对的,它不会受到伤害。你的循环指针(称之为p)将在循环结束时等于encodedEnd。但是在循环之后不需要访问任何东西(来自p或encodedEnd),所以这应该不是问题。我认为它也不会有所帮助,因为没有任何东西可以从encodedEnd写入或读取,因此无法优化。
但我同意你的前两个限制应该真的有帮助。