简体   繁体   English

传递整数文字时没有隐式转换警告?

[英]No implicit conversion warnings when passing integer literals?

I'm trying to understand when implicit conversions happen and to detect them to improve the quality of my codebase. 我试图了解隐式转换何时发生,并检测它们以提高我的代码库的质量。

I have enabled Wconversion and Wsign-conversion for this. Wconversion启用了WconversionWsign-conversion However I came across a situation where the compiler doesn't give any error. 但是我遇到了编译器没有给出任何错误的情况。 Example: 例:

#include <iostream>
#include <array>

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

Compiling: 编译:

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

Both the size of the array and the index to operator[] should be of type std::size_t (unsigned). 数组的大小和operator[]的索引都应该是std::size_t (unsigned)类型。 However I'm passing signed literals and there seems to be no problem. 但是我通过了签名的文字,似乎没有问题。 I could even pass 1.0F to operator[] and the compiler would be fine. 我甚至可以将1.0F传递给operator[] ,编译器也没问题。

If I create a signed variable for the index to operator[] , however, then the compiler does warn about implicit conversion. 但是,如果我为operator[]创建索引的signed变量,那么编译器会警告隐式转换。

What's happening under the hood? 引擎盖下发生了什么? Are implicit conversions happening when using literals? 使用文字时是否发生隐式转换? Why doesn't the compiler give an error? 为什么编译器没有出错? I'm using GCC 7.4 on Ubuntu 18.04. 我在Ubuntu 18.04上使用GCC 7.4。

The compiler does not warn you because it knows at compile time that this conversion if safe , ie, the original and target value are identical. 编译器不会警告您,因为它在编译时知道此转换是否安全 ,即原始值和目标值是否相同。 When you do: 当你这样做时:

vec[1.0F]

From a compiler point-of-view, there is no change of value (loss of precision) between 1.0F and 1 , so the compiler does not warn you. 从编译器的角度来看, 1.0F1之间没有值的变化(精度损失),因此编译器不会警告您。 If you try: 如果你试试:

vec[1.2F]

...the compiler will warn you because, eventhough 1.2F will be converted to 1 , there is a precision loss. ...编译器会警告你,因为虽然1.2F将转换为1 ,但是存在精度损失。

If you use a value that is not known at compile time, eg: 如果使用编译时未知的值,例如:

float get_float();

vec[get_float()];

You will get a warning as expected because the compiler does not know the value of get_float() beforehand and thus cannot be sure that the conversion is safe . 您将收到预期的警告,因为编译器事先不知道get_float()的值,因此无法确定转换是否安全

Note that you will never get such warning when constant expressions are expected (eg, in std::array<int, 10> ), because, by definition, constant expressions are known at compile time, so the compiler knows if there is an issue between the given value and the converted one. 请注意,在期望常量表达式时(例如,在std::array<int, 10> ),永远不会得到这样的警告,因为根据定义,常量表达式在编译时是已知的,因此编译器知道是否存在问题在给定值和转换后的值之间。

The warning "converting signed to unsigned" exists because some of these conversions can produce bad/unexpected results. 存在“将签名转换为无符号”的警告,因为其中一些转换可能会产生错误/意外结果。 Converting a signed 1 to unsigned yields 1 without any issues. 将带符号1转换为无符号会产生1而不会出现任何问题。 Converting -3 to unsigned is problematic. -3转换为无符号是有问题的。

With a variable, the compiler cannot (in the general case) know what its value will be at runtime, and so it has to warn about a potential conversion issue. 对于变量,编译器不能(在一般情况下)知道它在运行时的值,因此它必须警告潜在的转换问题。 With a literal, its value is known at compile time and so the compiler can either silently do the right thing (when the value converts OK), or warn/error out when necessary (when the conversion is problematic). 使用文字,其值在编译时是已知的,因此编译器可以静默地执行正确的操作(当值转换为OK时),或者在必要时警告/错误输出(当转换有问题时)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM