При изучении примера кода для этот вопрос Я предполагал, что это было Неопределенное Поведение, которое предотвращало последующее использование std::cout
из печати. Но оказывается, что попытка напечатать нулевой указатель std::ios_base::badbit
а также std::ios_base::failbit
быть установленным в своем состоянии потока которая была реальной причиной его неработоспособности. Из-за этого мне сейчас любопытно, действительно ли это является Неопределенное поведение (попытка) напечатать нулевой указатель. Итак, вот мои вопросы:
Это неопределенное поведение для печати нулевого указателя? Если это так, что может быть причиной этого в потоковом инсерторе? Я почти уверен, что вставщик достаточно умен, чтобы не разыменовывать нулевой указатель.
Я также хотел бы знать, почему вставщик устанавливает свою маску ошибки при обнаружении нулевого указателя в этом контексте (в частности, badbit
). Почему это не относится к завершению строкового литерала?
У меня нет под рукой стандарта, и я пока нашел только один источник, который, к сожалению, привел к неработающей ссылке.
basic_ostream
«s operator<<(basic_ostream<>&, const char*)
Функция требует, чтобы char*
не является нулевым — он предназначен для печати строки, на которую указывает указатель. Так что это неопределенное поведение, чтобы отправить ноль char*
в cout
, (См. C ++ 11 27.7.3.6.4 / 3 «Шаблоны функций вставки символов»).
Тем не мение, basic_ostream
«s operator<<(basic_ostream<>&, const void*)
Функция просто печатает значение указателя, поэтому нулевой указатель будет корректно работать с этой перегрузкой.
НКУ ostream.tcc
строка 319:
template<typename _CharT, typename _Traits>
basic_ostream<_CharT, _Traits>&
operator<<(basic_ostream<_CharT, _Traits>& __out, const char* __s)
{
if (!__s)
__out.setstate(ios_base::badbit);
gcc просто выполняет проверку того, что стандарт не гарантирует, что хорошо, потому что в любом случае он не определен.