Нет неявных предупреждений преобразования при передаче целочисленных литералов? - PullRequest
4 голосов
/ 19 июня 2019

Я пытаюсь понять, когда происходят неявные преобразования, и обнаружить их, чтобы улучшить качество моей кодовой базы.

Я включил Wconversion и Wsign-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[], компилятор предупреждает о неявном преобразовании.

Что происходит под капотом? Неявные преобразования происходят при использовании литералов? Почему компилятор не выдает ошибку? Я использую GCC 7.4 в Ubuntu 18.04.

Ответы [ 2 ]

8 голосов
/ 19 июня 2019

Компилятор не предупреждает вас, потому что он знает во время компиляции , что это преобразование, если безопасно , т.е. исходное и целевое значение идентичны. Когда вы делаете:

vec[1.0F]

С точки зрения компилятора не происходит изменения значения (потеря точности) между 1.0F и 1, поэтому компилятор не предупреждает вас. Если вы попробуете:

vec[1.2F]

... компилятор предупредит вас, потому что даже если 1.2F будет преобразовано в 1, потеря точности.

Если вы используете значение, которое не известно во время компиляции, например ::

float get_float();

vec[get_float()];

Вы получите предупреждение, как и ожидалось, потому что компилятор не знает заранее значение get_float() и, следовательно, не может быть уверен, что преобразование безопасно .

Обратите внимание, что вы никогда не получите такого предупреждения, когда ожидаются константные выражения (например, в std::array<int, 10>), потому что, по определению, константные выражения известны во время компиляции, поэтому компилятор знает, есть ли проблема между заданным значение и преобразованное.

6 голосов
/ 19 июня 2019

Предупреждение "преобразование подписанного в неподписанное" существует, поскольку некоторые этих преобразований могут привести к плохим / неожиданным результатам. Преобразование подписанного 1 в беззнаковое дает 1 без каких-либо проблем. Преобразование -3 в без знака проблематично.

С переменной компилятор не может (в общем случае) знать, каким будет ее значение во время выполнения, и поэтому он должен предупредить о потенциальной проблеме преобразования. С литералом его значение известно во время компиляции, и поэтому компилятор может либо молча делать правильные вещи (когда значение преобразуется в порядке), либо выводить предупреждение / ошибку, когда это необходимо (если преобразование проблематично).

...