C语言pure、const、unsequenced、reproducible属性差异解析
关于C23
[[unsequenced]]/[[reproducible]]与GCC pure/const属性的理解验证 C23标准新增了[[unsequenced]]和[[reproducible]]两个函数属性,目前GCC已支持这两个属性,同时保留了原有的pure、const属性。我对这四个属性的具体差异存在疑惑,现有资料大多仅对比其中一两个属性,未同时覆盖全部四个。请问我对它们的如下理解是否正确?
| 属性 | 副作用 | 输出方式 | 读取全局变量[0] | 写入全局变量[0] | 读取指针参数 | 写入指针参数 | 示例 | 优化方式 |
|---|---|---|---|---|---|---|---|---|
pure | 无副作用 | 仅通过返回值输出 | 允许读取非易失性全局变量[1] | 禁止 | 允许读取指向内容 | 禁止写入指向内容 | strlen、memcpy | 全局变量与参数未变化时,可省略重复调用 |
const | 无副作用 | 仅通过返回值输出 | 仅允许读取不会改变返回值的常量[2] | 禁止 | 仅允许读取常量指针指向内容[2] | 禁止写入指向内容 | abs | 相同参数调用返回值一致,可编译期求值 |
[[unsequenced]] | 允许有副作用 | 仅通过返回值输出 | 仅允许读取不会改变返回值的常量 | 禁止 | 允许读取指向内容 | 禁止写入指向内容 | strlen | 函数调用顺序可被编译器重排 |
[[reproducible]] | 允许有副作用 | 可通过返回值或修改指针参数输出 | 仅允许读取不会改变返回值的常量 | 禁止 | 允许读取指向内容 | 允许写入指向内容 | memcpy | 相同参数的重复调用可被省略 |
| 无属性 | 允许有副作用 | 可通过返回值/参数/全局变量输出 | 允许读取 | 允许 | 允许读取指向内容 | 允许写入指向内容 | printf | 无特殊优化 |
脚注
[0]:此处“全局变量”包含static和thread_local类型的变量。
[1]:GCC官方文档说明:
被
pure属性声明的函数可以安全地读取任何非易失性对象。
[2]:GCC官方文档说明:
被
const属性声明的函数可以安全地读取不会改变其返回值的对象,比如非易失性常量。
注意:如果指针指向的数据可能在函数的连续调用之间发生变化,那么带有指针参数并检查指向数据的函数不得被声明为const。
一般来说,由于函数无法区分可能变化和不会变化的数据,const函数永远不应该接受指针(或C++中的引用)参数。
参考资料
- C23的
[[reproducible]]和[[unsequenced]]属性的使用场景说明 - C++11
constexpr与C23[[reproducible]]的差异对比 - GNU C中
__attribute__((const))与__attribute__((pure))的区别 - GCC官方函数属性文档
内容的提问来源于Stack Exchange,提问作者Anon
相关产品推荐
相关产品推荐

