如何让GCC知晓只读访问函数不修改内存,无需重新加载值
需求与问题
测试代码
#include <stdio.h> typedef char*(*g)(const char*) __attribute__((__access__(__read_only__, 1))) ; char *h(const char*) __attribute__((__access__(__read_only__, 1))) ; // 非string.h中的声明,此处自定义! char *strdup(const char*); int main() { g f = h; // 将h改为strdup可查看效果 char c[2] = "0"; f(c); printf("%c\n", c[0]); return 0; }
需求
希望GCC编译上述代码时,调用printf无需从内存重新加载c[0]的值,同时要求方案支持函数指针调用场景。
尝试与现象
- 由于
const修饰符易被强制转换,编译器不会基于它做优化,这在预料之中;因此尝试使用__access__(__read_only__, 1)属性,但未产生效果。 - 当将代码中的
g f = h改为g f = strdup时,得到了期望的优化效果:- 调用
h时生成的汇编(未优化):call h movsbl 14(%rsp), %esi // 从内存加载c[0] movl $.LC0, %edi xorl %eax, %eax call printf - 调用
strdup时生成的汇编(符合期望):call strdup movl $48, %esi // 直接使用常量"0"的ASCII值 movl $.LC0, %edi // GCC识别到c的内容未被修改 xorl %eax, %eax call printf
- 调用
- 值得注意的是,即使使用自定义的
strdup声明(而非string.h中的标准声明),编译器依然能识别该函数不会修改c的内容,从而执行上述优化,这看起来是GCC内置了针对strdup的特殊优化规则。
核心问题
如何让GCC对自定义函数h(最好支持通过函数指针调用的场景)执行同样的优化?
更新说明
- 更新:因部分评论者对示例用单个char而非合法字符串感到困惑,已修改示例,并突出核心问题。
- 更新2:已将汇编结果复制到问题中,无需跳转外部链接查看。
内容的提问来源于stack exchange,提问作者UniversE
相关产品推荐
相关产品推荐

