本文介绍了cl x64:无符号长外部/内部联合:错误C2099:初始化程序不是常量/没有错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

案例1.文件: test1.c :

unsigned long val = (unsigned long)&"test";

int main()
{
    return 0;
}

编译器调用: cl test1.c/c

结果:

Microsoft (R) C/C++ Optimizing Compiler Version 19.25.28611 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

test1.c
test1.c(1): warning C4311: 'type cast': pointer truncation from 'char (*)[5]' to 'unsigned long'
test1.c(1): error C2099: initializer is not a constant

案例2.文件: test2.c :

union { unsigned long val; } val =  { (unsigned long)&"test" };

int main()
{
    return 0;
}

编译器调用: cl test2.c/c

结果:

Microsoft (R) C/C++ Optimizing Compiler Version 19.25.28611 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

test2.c
test2.c(1): warning C4311: 'type cast': pointer truncation from 'char (*)[5]' to 'unsigned long'

问题:为什么将 unsigned long 放入 union (案例2,文件test2.c)后,为什么错误C2099:初始化器不是常量不见了?

Question: why after putting unsigned long into union (case 2, file test2.c) the error C2099: initializer is not a constant is gone?

注意:

    两种代码版本的
  • cl x86 (与x64版本相同)不会产生错误,也不会发出警告.

  • for both code versions cl x86 (same version as for x64) produces NO errors, NO warnings.

两个代码版本 gcc x86/x64 (版本9.3.0)均不会产生错误,也不会发出警告.

for both code versions gcc x86/x64 (version 9.3.0) produces NO errors, NO warnings.

UPD.请注意:问题不是关于安全代码/不安全代码还是错误代码/正确代码.问题是关于 cl 编译器的行为.IE.为什么在第二种情况下,cl认为 initializer是一个常量(这样的结论是由于没有错误消息).

UPD. Please note: the question is not about safe code / unsafe code or wrong code / right code. The question is about cl compiler behavior. I.e. why in the 2nd case the cl considers that initializer IS a constant (such conclusion is from the absence of the error message).

推荐答案

静态存储持续时间对象的初始化程序必须为恒定表达式.

Initializers for objects of static storage duration must be constant expressions .

在C89标准中( Microsoft C符合),在常量表达式中不允许从指针强制转换为整数.

In the C89 standard (the only standard to which Microsoft C conforms) , a cast from pointer to integer is not permitted in a constant expression.

这是一个语义规则,而不是约束条件,这意味着程序具有未定义的行为,而无需诊断.因此,允许编译器拒绝该程序(但不要求拒绝它),它可以发出或可以不发出诊断信息,并且不要求未定义的各种程序之间具有一致性.

This is a Semantic rule and not a Constraint, which means the program has undefined behaviour with no diagnostic required. Therefore the compiler is permitted to reject the program (but is not required to reject it), it may or may not issue diagnostics, and there is no requirement of consistency amongst various programs that are undefined.

我们不能从没有错误消息的结论中得出初始化器被接受为常量的结论.

We cannot conclude from the absence of an Error message that the initializer was accepted as a constant .

自C99以来,该标准还包括文本实现可以接受其他形式的常量表达式".尽管我找不到用于MSVC的文档,但编译器应发布一致性文档,列出其接受为常量的表达式.(如果可以的话,发表评论!)

Since C99, the standard also includes the text "An implementation may accept other forms of constant expressions". The compiler should publish conformance documentation listing which expressions it accepts as constants, although I couldn't find that documentation for MSVC. (leave a comment if you can!)

可能有必要注意有关将指针转换为 unsigned long 的规则.根据最新标准:

It may also be relevant to note the rules about casting pointer to unsigned long. From the latest Standard:

因此,即使C99或C11兼容的编译器说明它接受常量表达式中从指针到整数的强制转换,强制转换的结果仍然可能会导致启动时出现陷阱或导致未定义的行为(其中,像以前一样,意味着无需进行诊断,并且该程序可能会被拒绝.)

So, even if the C99 or C11-compliant compiler documents that it accepts casts from pointer to integer in constant expressions, it may still be that the result of the cast causes a trap on startup, or causes undefined behaviour (which , as before, means no diagnostic is required and the program may be rejected).

这篇关于cl x64:无符号长外部/内部联合:错误C2099:初始化程序不是常量/没有错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-01 22:26