pure 是一个函数属性,表示函数不会修改任何全局内存 const 是一个函数属性,表示函数不会读取/修改任何全局内存。
鉴于该信息,编译器可以进行一些额外的优化。
GCC的例子:
float sigmoid(float x) __attribute__ ((const));
float calculate(float x, unsigned int C) {
float sum = 0;
for(unsigned int i = 0; i < C; ++i)
sum += sigmoid(x);
return sum;
}
float sigmoid(float x) { return 1.0f / (1.0f - exp(-x)); }
在该示例中,编译器可以将函数 calculate 优化为:
float calculate(float x, unsigned int C) {
float sum = 0;
float temp = C ? sigmoid(x) : 0.0f;
for(unsigned int i = 0; i < C; ++i)
sum += temp;
return sum;
}
或者如果您的编译器足够聪明(并且对浮点数不那么严格):
float calculate(float x, unsigned int C) { return C ? sigmoid(x) * C : 0.0f; }
如何为不同的编译器(即GCC,Clang,ICC,MSVC或其他编译器)以这种方式标记函数?
答案 0 :(得分:28)
通常,似乎几乎所有编译器都支持GCC属性。到目前为止,MSVC是唯一不支持它们的编译器(也没有任何替代方案)。
答案 1 :(得分:4)
首先,注意&#34; const&#34;是一个更严格的版本 &#34;纯粹&#34;,所以&#34;纯粹&#34;如果编译器没有,可以用作后备 实施&#34; const&#34;。
正如其他人所说,MSVC并没有真正有类似的东西,
但很多编译器都采用了GCC语法,包括很多
哪些不定义__GNUC__
(有些人有时会这样做
有时候不要,视标志而定。)
__has_attribute(pure)
和
__has_attribute(const)
来检测它们,但它可能很好
只依靠clang设置__GNUC__
。这还包括编译器
基于像emscripten和XL C / C ++ 13 +这样的clang。__TI_GNU_ATTRIBUTE_SUPPORT__
检测到)支持两者。其中,clang总是定义__GNUC__
和朋友(目前为
4.2,IIRC)。英特尔默认定义__GNUC__
(尽管可以
用-no-gcc抑制)和C ++模式下的PGI一样(但不是用C语言
模式)。您必须手动检查其他人。
Oracle Developer Studio也支持pragma,因为它已知 为Forte Developer 6。他们&#39;再 使用方式略有不同,因为它们要求您指定功能 名:
/* pure: */
#pragma does_not_write_global_data (funcname)
/* const; SPARC-only until 12.2 */
#pragma no_side_effect (funcname)
TI 6.0+(至少)支持C ++中的#pragma FUNC_IS_PURE;
pragma
仅模式。在C模式下,它是#pragma FUNC_IS_PURE(funcname);
。
大部分内容可以隐藏在宏的背后,这就是我所做的 Hedley:
#if \
HEDLEY_GNUC_HAS_ATTRIBUTE(pure,2,96,0) || \
HEDLEY_INTEL_VERSION_CHECK(16,0,0) || \
HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
HEDLEY_TI_VERSION_CHECK(8,0,0) || \
(HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
HEDLEY_PGI_VERSION_CHECK(17,10,0)
# define HEDLEY_PURE __attribute__((__pure__))
#elif HEDLEY_TI_VERSION_CHECK(6,0,0) && defined(__cplusplus)
# define HEDLEY_NO_RETURN _Pragma("FUNC_IS_PURE;")
#else
# define HEDLEY_PURE
#endif
#if HEDLEY_GNUC_HAS_ATTRIBUTE(const, 2, 5, 0) || \
HEDLEY_INTEL_VERSION_CHECK(16,0,0) || \
HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
HEDLEY_TI_VERSION_CHECK(8,0,0) || \
(HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
HEDLEY_PGI_VERSION_CHECK(17,10,0)
# define HEDLEY_CONST __attribute__((__const__))
#else
# define HEDLEY_CONST HEDLEY_PURE
#endif
这并不包括需要该功能的变体 将名称作为参数,但它仍然涵盖浩大的大多数 用户,在任何地方都可以安全使用。
如果你不想使用Hedley(它是一个公共领域/ CC0标题),它 不应该更换内部版本宏太困难。如果 你选择这样做,你应该把你的端口建立在 Hedley回购代替了这个答案,因为我更有可能保留它 最新的。