GCC具有pure和const属性,其中const实际用于真正的纯函数(纯为idempotent functions which are also side-effect free)。如何在gcc中声明和定义纯函数?
那么我该如何声明和定义一个函数使用常量属性?
编辑:我对真正的纯函数感兴趣,这些纯函数是用const属性声明的,而不是用纯属性声明的。
GCC具有pure和const属性,其中const实际用于真正的纯函数(纯为idempotent functions which are also side-effect free)。如何在gcc中声明和定义纯函数?
那么我该如何声明和定义一个函数使用常量属性?
编辑:我对真正的纯函数感兴趣,这些纯函数是用const属性声明的,而不是用纯属性声明的。
实施例:
// Declaration:
int square (int x) __attribute__ ((const));
// Definition:
int __attribute__ ((const)) square (int x)
{
return x*x;
}
的语法的所有属性是非常相同:__attribute__ ((<attribute-name>))
,或__attribute__ ((<attribute-name> (<attribute-options>)))
。从您链接到的文档中引用:
关键字
__attribute__
允许您在进行声明时指定特殊属性。该关键字后面跟着一个双括号内的属性规范。
有您链接到其他几个属性的文档中的例子,包括pure
:
int square (int) __attribute__ ((pure));
因此,所有你需要的,语法的角度来看,使用const
,是改变pure
到const
:
int square (int) __attribute__ ((const));
正如在评论中指出:如果你在一个定义使用它,那么你需要把__attribute__ ((const))
在不同的位置:
int square (int) __attribute__ ((const)) { ... } // doesn't work
int __attribute__ ((const)) square (int) { ... } // does work
但const
和pure
属性是几乎唯一有用如果它们适用于外部声明,那么这应该不成问题。如果定义可见,GCC通常可以在没有您的帮助的情况下确定该功能是否可以被视为const
/pure
。
根据本this article,语法与@hvd说什么相匹配:
int square (int) __attribute__ ((pure));
然而,似乎gcc
当我编译下面的例子并不强制不检查全局状态的财产。
#include <stdio.h>
int square (int) __attribute__ ((pure));
int outerX = 7;
int square(int x) {
return outerX * x;
}
int main(){
printf("%d\n", square(5));
return 0;
}
以下打印没有错误,代码运行并产生35
。
gcc -Wall -Werror -pedantic -O3 Pure.c
gcc --version
gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
更奇怪的是,gcc
也没有,如果我们发生变异函数内部的全局状态和每个调用返回,因为它在全球所引起的状态变化的不同值在意。
#include <stdio.h>
int square (int) __attribute__ ((pure));
int outerX = 7;
int square(int x) {
outerX++;
return outerX * x;
}
int main(){
printf("%d\n", square(5));
printf("%d\n", square(5));
printf("%d\n", square(5));
return 0;
}
输出:
40
45
50
从C++ 11开始,可以使用attribute specifier sequence来指定这些属性。例如:
[[ gnu::const ]]
int square (int x)
{
return x * x;
}
另外,从C++ 17开始,编译器未知的所有属性都会被忽略而不会导致错误。所以上面的代码可以在不同的编译器和平台之间移植。
是的,文档有点误导我认为:函数是否纯粹取决于它的功能,而不是它是如何实现的。如果函数是纯粹的,即使它读取全局变量(例如,因为这些变量永不改变),那么它可能被声明为纯粹的。因此,编译器不能强制执行该属性。 – hvd 2015-02-09 09:01:02
它仍然是有意义的,你的编辑:'纯粹(无效)__attribute __((纯)); int pure(void){static bool pureInited = false; static int pureValue;如果(!pureInited){pureValue = ...; pureInited = true; }返回pureValue; }'我认为可以在那里应用'pure'属性,即使函数使用静态存储持续时间来修改变量:效果仍然是该函数始终返回完全相同的值。 ('const'也可能在这里有意义,而不是'pure')。 – hvd 2015-02-09 09:08:38
@hvd,你认为如果函数在每次调用时都返回不同的值并且参数相同,编译器就会大声嚷嚷? – merlin2011 2015-02-09 09:10:43