我有一个函数,它接收两个数组并将pure
函数的结果写入第三个数组(c_i = a_i / b_i):
inline
void array_division (ptrdiff_t nmemb,
double dest[static nmemb],
const double src1[static nmemb],
const double src2[static nmemb])
__attribute__((nonnull, pure));
inline
void array_division (ptrdiff_t nmemb,
double dest[static nmemb],
const double src1[static nmemb],
const double src2[static nmemb])
{
for (ptrdiff_t i = 0; i < nmemb; i++)
dest[i] = src1[i] / src2[i];
}
GCC引发错误,因为它不希望纯函数返回void
。
pure function是一个根据其参数以及这些参数所指向的值的函数;并且如果两个调用之间的参数或它们所指向的值均未更改,则它们应该是多余的,并且可以忽略该调用,并评估为上一个调用返回的相同值。
我的函数遵循所有这些规则:如果三个数组在两个函数调用之间均未更改,则可以完全删除该函数调用;并且它们求值的值相同(没有值,因为它是void
)。
我认为GCC应该允许使用__attibute__((pure))
吗?
我应该返回假的return 0;
以避免GCC抱怨吗?
编辑:
GCC中的错误状态:__ attribute __((pure)) to function with non-const pointers
答案 0 :(得分:3)
关于return 0;
起作用的原因...
根据{{3}}:
由于纯函数不能具有任何可观察到的副作用,因此使此类函数返回
void
毫无意义。声明了这样的功能。
但也请注意,您无法返回void
的原因是:没有道理。您将放弃返回值的能力,而返回值只是纯函数的唯一合法目的。
pure
属性禁止函数修改程序的状态,该状态可以通过检查函数的返回值以外的其他方式来观察。
这意味着,例如,标记为pure
的函数被禁止在您传入的数组中设置条目。令我有些惊讶的是,它完全允许使用非常量指针,而通过它进行的赋值要少得多他们。
至于一旦您欺骗了GCC允许对这种功能进行修改,会发生什么,我不确定。在这种情况下,取决于GCC指定的操作。
答案 1 :(得分:1)
您的函数不遵循纯函数的规则。链接到文本的内容很清楚,多次表示,不允许通过传递给函数的指针来更改程序的可观察状态。从纯函数中唯一可以观察到的是它的返回值。 通过非常量指针修改内存不会返回值,但是会产生副作用。
您的功能不纯,因为它有副作用。如果优化器认为纯函数的返回值未使用,则根本不需要调用,甚至第一次也不需要。
因此,void函数不能用作纯函数,因为它是必须可优化为void nop() { }
的函数。这没有任何意义。
这里唯一的编译器和文档错误是,当您添加双重错误的返回值0时,编译器抑制了诊断。
您发现了另一组可能具有优化属性的函数-幂等。但是,问题是只能消除重复的调用-但是与在循环条件下使用strlen
不同,几乎没有任何理由使用相同的参数重复调用幂等函数。