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

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

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

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

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

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

或者通过将它添加到所有三个参数中我是否有一些好处?

我可以看到,使输入和输出缓冲区restrict有助于编译器知道它们不重叠。 但是由于最后一个参数encodedEnd仅用于标记输出缓冲区的结尾,我认为restrict对这里的编译器没有任何帮助(虽然我认为它不会伤害,除了添加function声明中不必要的噪音)。

试试Mike Acton的文章。 由于不使用它的性能影响以及错误使用它的后果,限制是可怕的。

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

在这种特殊情况下, encodeEnd是否为limit是没有区别的; 你已经向编译器承诺没有人对未编码编码进行别名,因此读写操作不会相互干扰。

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

 encoded == unencoded+1 

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

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

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