请考虑下面的C程序:

double local_array[10];
double *p = local_array+i;
/* local computations */
f(); // f() cannot modify the local_array since the local_array has not escaped
*p += 5.0;

如果已知f()正常返回,则可以在调用之前移动*p += 5.0;,也许是为了提高效率(可以将加载-浮点加法-存储序列与前面的计算混合在一起).

然而,如果不知道f()正常返回,这很可能是相对于标准而言是非法的.事实上,如果f()打印一条错误消息并退出,则在其前面加上可能失败的对*p的访问将是危险的(错误的指针,因为值i不正确).我们无法知道p是否指向有效的、可写的内存.可能f()会执行排除无效值p的判断.

所以我的问题是:有没有办法告诉编译器(也许是GCC或clang)一个函数总是正常返回的?

有一个nothrow的属性,但它似乎略有不同.

这样的属性将是noreturn的"DUAL",这意味着函数永远不会返回.

如果您想知道这是怎么回事:PostgresSQL bug #616180是关于gcc的旧版本,假设它们可以在终止程序执行的函数调用之前进行类似的trap 指令移动(由于检测到内部错误).

推荐答案

对于GCC:不,这样的属性不存在,甚至在编译器内部也不存在(截至GCC 13).

对于Clang/LLVM:LLVM IR具有willreturn function attribute,但Clang不将其公开给C和C++.

C++相关问答推荐

插入元素后,Sizeof操作符无法正常工作

数组元素的编号索引

位屏蔽对于无符号转换是强制的吗?

使用SWI—Prolog的qsave_program生成二进制文件有什么好处?'

丑陋的三重间接:可扩展的缓冲区管理 struct

ZED for SDL上的C语言服务器

Make Node函数.S有什么问题吗?

初始变量重置后,char[]的赋值将消失

如何有效地编写代码来判断两个元素数量相同的数组即使在不同的位置也具有相同的元素?

FRIDA-服务器成为端口扫描的目标?

等同于铁 rust 的纯C语言S未实现!()宏

如何在VS 2022中正确安装额外的C头文件

链表删除 node 错误

当我用scanf(&Q;%S%S%S&Q;,单词0,单词1,单词2)输入多个单词时,除了最后一个单词外,每个单词的第一个字符都丢失了

C中的回文数字

问题:C#Define上的初始值设定项元素不是常量

从Raku nativecall调用时精度不同

在我的第一个C语言中观察到的错误';你好世界';程序

如何找出C中分配在堆上的数组的大小?

是什么阻止编译器优化手写的 memcmp()?