【问题标题】:No implicit conversion warnings when passing integer literals?传递整数文字时没有隐式转换警告?
【发布时间】:2019-06-19 07:23:25
【问题描述】:

我试图了解隐式转换何时发生并检测它们以提高我的代码库的质量。

我为此启用了WconversionWsign-conversion。但是我遇到了编译器没有给出任何错误的情况。示例:

#include <iostream>
#include <array>

int main()
{
   std::array<int, 10> vec{};
   std::cout << vec[1] << std::endl; 
}

编译:

$ g++ --std=c++14 -Wall -Wextra -Werror -pedantic -Wsign-conversion -Wconversion test.cpp 
$ 

数组的大小和operator[] 的索引都应该是std::size_t 类型(无符号)。但是我正在传递签名文字,似乎没有问题。我什至可以将1.0F 传递给operator[],编译器就可以了。

如果我为operator[] 的索引创建一个有符号变量,那么编译器会警告隐式转换。

幕后发生了什么?使用文字时是否会发生隐式转换?为什么编译器不报错?我在 Ubuntu 18.04 上使用 GCC 7.4。

【问题讨论】:

  • 您不会收到警告,因为编译器在编译时就知道这些转换没问题,如果您使用编译时不知道的东西,您将按预期收到警告。

标签: c++ implicit-conversion


【解决方案1】:

编译器不会警告您,因为它在编译时知道此转换是否安全,即原始值和目标值相同。当你这样做时:

vec[1.0F]

从编译器的角度来看,1.0F1 之间的值没有变化(精度损失),因此编译器不会警告您。如果你尝试:

vec[1.2F]

...编译器会警告您,因为即使1.2F 将转换为1,也会有精度损失。

如果使用编译时未知的值,例如:

float get_float();

vec[get_float()];

您将按预期收到警告,因为编译器事先不知道get_float() 的值,因此无法确定转换是否安全

请注意,当需要常量表达式时(例如,在std::array&lt;int, 10&gt; 中),您永远不会收到此类警告,因为根据定义,常量表达式在编译时是已知的,因此编译器知道给定表达式之间是否存在问题值和转换后的值。

【讨论】:

  • 我明白了,谢谢!这种行为是由标准保证的还是依赖于编译器的?我想知道是否最好保护自己并明确“例如数组 [0U]”,以防某些编译器在这里有奇怪的行为。例如,PClint 在运行静态分析时抱怨这一点 (MISRA C++ 2008 5-0-4)
  • @user1011113 您无法保证此类代码的警告,因为标准未强制规定警告。您可以确定的是array[0] 必须在任何编译器上编译,即使有些可能会发出警告。我个人会使用array[0],因为我没有看到明确表达的好处,但这是一个选择问题。
【解决方案2】:

存在“将有符号转换为无符号”警告是因为部分这些转换可能会产生不良/意外结果。将已签名的 1 转换为未签名的 1 不会出现任何问题。将-3 转换为无符号是有问题的。

对于变量,编译器(在一般情况下)无法知道它在运行时的值,因此它必须警告潜在的转换问题。使用文字,它的值在编译时是已知的,因此编译器可以静默地做正确的事情(当值转换 OK 时),或者在必要时发出警告/错误(当转换有问题时)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-02
    相关资源
    最近更新 更多