【问题标题】:Narrowing conversion from `int` (constant expression) to `unsigned int` - MSVC vs gcc vs clang缩小从`int`(常量表达式)到`unsigned int`的转换-MSVC vs gcc vs clang
【发布时间】:2017-08-21 21:55:48
【问题描述】:
constexpr int i = 100;
struct F { F(unsigned int){} };
int main() { F{i}; }

上面的sn-p:

  • g++ 7-Wall -Wextra -Wpedantic 上编译没有警告

  • clang++ 4-Wall -Wextra -Wpedantic 上编译没有警告

  • MSVC 2017 上编译失败:

    从“const int”到“unsigned int”的转换需要缩小转换

问:这里是 MSVC 错了吗?

live example on godbolt.org


int i = 100;
struct F { F(unsigned int){} };
int main() { F{i}; }
  • g++ 7-Wall -Wextra -Wpedantic 上编译带有警告

    将“i”从“int”缩小到“unsigned int”

  • 无法用-Wall -Wextra -Wpedantic 编译clang++ 4

    在初始化列表中,非常量表达式不能从“int”类型缩小到“unsigned int”

  • MSVC 2017 上编译失败:

    从 'const int' 到 'unsigned int' 的转换需要缩小转换

问:这里g++错了吗? (即它应该产生一个硬错误吗?)

live example on godbolt.org

【问题讨论】:

  • 大多数时候标准只是说“诊断”,它涵盖了警告和错误。
  • @ShafikYaghmour:我明白了,谢谢。我假设 MSVC 在第一个 sn-p 中是错误的呢?根据 Richard 的说法,我认为 g++ 和 clang++ 在 sn-ps 中都是兼容的。
  • 使用 GCC,要将标准强制诊断转换为错误,但仅限标准强制诊断,请使用 -pedantic-errors,尽管如上所述的警告足以满足标准要求。

标签: c++ c++11 visual-c++ type-conversion language-lawyer


【解决方案1】:

从不要求任何 C++ 程序产生硬错误。有打印诊断的要求。标准未指定诊断的形式:一个老笑话是打印出一个空格就可以满足标准的诊断要求。这将是一个实施质量问题。

有一些格式不正确的程序,标准对其行为没有任何限制,有时是强制性诊断。

在某些情况下,程序格式不正确,需要进行诊断。处理该问题的一种方法是生成一条消息,说明这是一个错误,然后不生成任何要运行的二进制文件。另一种方法是生成一条消息说这是一个警告,然后生成一个可以运行的二进制文件。

所以,g++在仅仅打印一个警告的标准下并没有错。

生成的程序在技术上都是未定义的行为; g++ 可以在运行时格式化您的硬盘而不违反标准。这将被视为实施质量问题。

Shafik's answer here 涵盖了第一个问题。 i 是常量表达式,其值符合目标类型;缩小转换应该没有警告或错误。

C++ 标准不能保护您免受恶意编译器的攻击。

据报道,当标准要求生成的程序格式错误时,-pedantic-errors 可以传递给 g++ 以使其生成硬错误而不是警告。

【讨论】:

  • 谢谢,澄清了我所有的疑惑。如果它还没有,我会报告给 MSVC 跟踪器。
  • 如果标准能够阐明未能禁止某种行为并不意味着不应将以该方式运行的编译器视为严重劣于以某种其他方式运行的编译器,这将是有帮助的,其他一切都是平等的。标准不要求实现接受程序#2,并允许实现通过他们认为合适的任何方式指示错误是合理的,但这并不意味着给定的质量实现# 2 不应以受限的方式行事。
  • @supercat 这是一个实施质量问题。编译器不违反标准的事实是一个笑话," " 是一个有效的诊断消息。当没有问题时,试图强制执行这种东西是愚蠢的,没有真正的“真正”编译器会故意做这样愚蠢的邪恶事情。
  • @Yakk:有几个问题: 1. 编译器以过去几年被认为是愚蠢的方式行事已成为时尚; 2.一个好的标准应该能够做出坚实的保证,而现在的标准确实做不到。例如,应该有定义的实现集(“安全符合”)和程序(“选择性符合”),以便将后一组中的任何程序提供给前一组中的任何编译器,在最坏的情况下,会以未指定的方式从中选择一组定义的实现定义的行为。
  • @Yakk:例如,对于符合安全一致性的实现,它必须指定在发生堆栈溢出时它可能会采取的行为方式,或者提供可以实现的方法静态验证在给定选择性符合程序时不会发生堆栈溢出(添加语言固有的堆栈检查将使对这种保证的支持变得实用,即使对于使用函数指针和递归的程序也是如此)。并非所有的实现都可以支持这样的保证,但是让一组可以由...完成的任务是切实可行的。
猜你喜欢
  • 1970-01-01
  • 2021-01-02
  • 2020-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多