Почему это компилируется и есть ли какой-либо переключатель компилятора, который может заставить компилятор сообщать об этом как об ошибке или предупреждении?

#c #qt #g

#c #qt #g

Вопрос:

Я нашел этот пример, когда запускал PCLint в исходном коде проекта, над которым я работаю. Вот фрагмент кода:

 QString foo()
{
    return false;
}
  

Я скомпилировал код и проверил, что он возвращает пустую строку. Реальный пример — большой метод в большом классе, и где-то в какой-то удаленной ветке if было это изолированное

 return false;
  

Хорошо, это плохое кодирование, позор разработчику (используя SVN / blame, я мог бы даже узнать, кто это сделал :-)) но, серьезно, почему компилятор не жалуется?

Моя теория заключается в том, что компилятор переводит

 return false;
  

Для

 return QString(((const char *) false));
  

Однако я не вижу всех элементарных шагов, выполняемых компилятором для вывода этого. Сначала он пробует все конструкторы QString и находит

 QString(const * char);
  

но тогда? Как он определяет, что он может перейти от bool к const char * . Или он автоматически преобразует bool к любому типу указателя каждый раз, когда вы используете bool, где ожидается указатель?

Вторая часть вопроса. Поскольку все эти неявные преобразования типов довольно опасны (зачем разработчику писать ‘return false;’, если они означают «вернуть пустую строку»?), Есть ли способ (например, переключатель компилятора), чтобы о таких ситуациях, по крайней мере, сообщалось как предупреждение? Я попробовал -Wall в g , и он не напечатал никакого предупреждения.

Редактировать

Спасибо за подсказки. false, похоже, имеет особое отношение. Если я сделаю

 return true;
  

Я получаю:

 error: conversion from ‘bool’ to non-scalar type ‘QString’ requested
  

Я использую g 4.4.3 в Ubuntu. Как указывалось в разных комментариях, другие компиляторы сообщают о проблеме.

Комментарии:

1. clang предупреждает об этом, был случай этого некоторое время назад.

2. GCC (по крайней мере, 4.5) предупреждает об этом.

3. Вставьте плагин для explicit конструкторов здесь.

4. Хорошо, я использую GCC 4.4.3, это может объяснить это. Спасибо.

5. Начиная с GCC 4.5 , новый (включенный по умолчанию) флаг called -Wconversion-null выводит предупреждение.

Ответ №1:

false равно нулю. Ноль — это особый случай, который представляет нулевой указатель и будет приведен к любому типу указателя без предупреждения.

Я очень удивлен, что компилятор разрешил это как одноэтапное преобразование и не рассматривал его как двухэтапное преобразование из boolean в int , затем int в char* — двухэтапные преобразования не выполняются неявно.

Комментарии:

1. Но false имеет тип bool, а 0 имеет тип int . Выполняется ли приведение автоматически?

2. GCC предупреждает об этом: warning: converting ‘false’ to pointer type for argument 1 of ‘QString::QString(const char*)’

3. Странно, я не получаю никаких предупреждений. Используя g (Ubuntu 4.4.3-4ubuntu5) 4.4.3. У меня есть -Wall в командной строке.

4. Я тоже был очень удивлен, вот почему я хотел сообщить об этом и попросить объяснений. Кстати, исходный пример был скомпилирован в Visual Studio 8.

5. bool является целочисленным типом, false преобразуется в 0 и является постоянным, и вы можете преобразовать постоянное целочисленное выражение, равное 0 для нулевого указателя. (Это не будет работать с true ; true преобразуется в 1, и для него нет специального значения указателя.)