微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

MSVC:为什么“#pragma fenv_access (on)”会导致“错误 C2099:初始化程序不是常量”?

如何解决MSVC:为什么“#pragma fenv_access (on)”会导致“错误 C2099:初始化程序不是常量”?

示例代码 (t50.c):

#pragma fenv_access (on)
float d = 0.0 + 0.0;
int main(void)
{
    return 0;
}

调用

$ cl t50.c /fp:strict
Microsoft (R) C/C++ Optimizing Compiler Version 19.25.28611 for x64
copyright (C) Microsoft Corporation.  All rights reserved.

t50.c
t50.c(2): error C2099: initializer is not a constant

问题:为什么 #pragma fenv_access (on) 会导致 error C2099: initializer is not a constant?原因/动机是什么?

是不是因为在#pragma fenv_access (on)cl不允许进行常量折叠?

解决方法

来自documentation

编译器禁用浮点优化,因此您的代码可以一致地访问浮点环境。
...
受 fenv_access 约束的优化类型有:

  • 全局公共子表达式消除

  • 代码运动

  • 不断折叠

1.0 + 1.0 视为常量是常量折叠的一个示例。

尽管语言指定这是一个常量表达式,因此它可以用作静态初始化程序,但编译指示覆盖了这种处理,因为它需要在运行时执行加法,以防设置浮点标志。

,

fenv_access pragma 文档特别指出:

编译器禁用浮点优化,因此您的代码可以一致地访问浮点环境。

因此看起来禁用的优化之一是常量的折叠,这意味着:

float d = 0.0 + 0.0;

需要在运行时而不是编译时计算。所以编译器是正确的,在那种情况下它不是常量。

,

如果 pip install --user pandas WARNING: Retrying (Retry(total=4,connect=None,read=None,redirect=None,status=None)) after connection broken by 'ProxyError('Cannot connect to proxy.',NewConnectionError('<pip._vendor.urllib3.connection.HTTPSConnection object at 0x000001EB96511730>: Failed to establish a new connection: [Errno 11001] getaddrinfo failed'))': /simple/pandas/ WARNING: Retrying (Retry(total=3,NewConnectionError('<pip._vendor.urllib3.connection.HTTPSConnection object at 0x000001EB96511580>: Failed to establish a new connection: [Errno 11001] getaddrinfo failed'))': /simple/pandas/ WARNING: Retrying (Retry(total=2,NewConnectionError('<pip._vendor.urllib3.connection.HTTPSConnection object at 0x000001EB96511610>: Failed to establish a new connection: [Errno 11001] getaddrinfo failed'))': /simple/pandas/ WARNING: Retrying (Retry(total=1,NewConnectionError('<pip._vendor.urllib3.connection.HTTPSConnection object at 0x000001EB9652F130>: Failed to establish a new connection: [Errno 11001] getaddrinfo failed'))': /simple/pandas/ WARNING: Retrying (Retry(total=0,NewConnectionError('<pip._vendor.urllib3.connection.HTTPSConnection object at 0x000001EB9652F2B0>: Failed to establish a new connection: [Errno 11001] getaddrinfo failed'))': /simple/pandas/ ERROR: Could not find a version that satisfies the requirement pandas (from versions: none) ERROR: No matching distribution found for pandas 应该具有与 #pragma fenv_access (on) 相同的效果,那么编译器就 C99 和 C11 标准而言是错误的。 但是,Microsoft 可能并不关心 C 标准,并且 MSVC 可能会以与标准 pragma 不同的方式解释 #pragma STDC FENV_ACCESS ON。 此答案解决了标准是否允许在 #pragma fenv_access (on) 之后。

在顶层,

#pragma STDC FENV_ACCESS ON

声明一个对象 float d = 0.0 + 0.0; ,具有静态存储持续时间和初始化程序 d。 表达式 0.0 + 0.0 是一个常量表达式。 因此,在支持 Annex F 浮点语义 (IEC 60559/IEEE 754) 的实现中,此处的 0.0 + 0.0 将在转换时进行评估(好像),在执行时对浮点环境没有影响.

C11,§F.8.4 常量表达式,¶1(强调):

浮动类型的算术常量表达式,在具有静态或线程存储持续时间的对象的初始值设定项中的表达式除外,在执行期间被评估(好像)...

示例

0.0 + 0.0

C11,§F.8.5 初始化,¶1:

...所有对具有静态或线程存储持续时间的对象进行初始化的计算都是在翻译时完成的(好像)。

示例

#include <fenv.h>
#pragma STDC FENV_ACCESS ON
void f(void)
{
  float w[] = { 0.0/0.0 };    // raise an exception
  static float x = 0.0/0.0;   // does not raise an exception
...

示例表明,即使打开 FENV_ACCESS,也允许在具有静态存储持续时间的对象的初始值设定项中使用涉及浮点算术的常量表达式。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。