5 ответов:
я понятия не имею о том, что делает опция [] в cout
это на самом деле не
coutвариант, что происходит это"\n"это строковый литерал. Строковый литерал имеет тип массив N const char на[]- это просто индекс в массив символов, который в данном случае содержит:\nПримечание
добавляется ко всем строковым литералам.в
==оператор приводит или правда или ложные, так что индекс будет:
0если false, еслиaНе равноNв результате\n1если true, еслиaравнаNв результатеэто довольно загадочно и можно было бы заменить простым
if.для справки стандарт C++14 (легкость подтвердил проект соответствует фактическому стандарту) С самым близким проектомN3936 в разделе
2.14.5строковые литералы [Лекс.строка] говорит (выделено мной):строковый литерал имеет тип "массив из N const char", где n - это размер строки, как определено ниже, и имеет статическую длительность хранения (3.7).
и:
после любой необходимой конкатенации, на этапе перевода 7 (2.2), '\0 ' добавляется к каждому строковому литералу так что программы, которые сканируют строку, могут найти ее конец.
раздел
4.5[conv.пром] говорит:значение prvalue типа bool может быть преобразовано в значение prvalue типа int, с помощью ложь становится нулем, а истина-единицей.
запись нулевого символа в текстовый поток
претензия была сделал это написание нулевого символа (
) для текстового потока является неопределенным поведением.насколько я могу судить, это разумный вывод,
coutопределяется в терминах потока C, как мы видим из27.4.2[узкий.поток.объекты] он говорит:объект cout управляет выводом в буфер потока, связанный с объектом stdout, объявленным в
(27.9.2). и проект стандарта C11 в раздел
7.21.2потоки говорит:[...]Данные, считанные из текстового потока, обязательно будут сравниваться с данными которые ранее были записаны в этот поток только если: данные состоят только из печати символы и управляющие символы горизонтальная вкладка и новая строка;
и печатные символы покрыты
7.4обработка символов: [...]термин контрольный символ относится к элементу набора символов, зависящего от языкового стандарта, который не печатается письмена.199) все буквы и цифры печатными буквами.
сноски
199говорю:в реализации, которая использует семибитовый набор символов US ASCII, печатные символы являются таковыми значения которых лежат от 0x20 (пробел) до 0x7E (Тильда); управляющие символы-это те, чьи значения от 0 (NUL) до 0x1F (US), и символ 0x7F (DEL).
и, наконец, мы видим, что результат отправки нулевого символа не указан, и мы можем видеть, что это неопределенное поведение из раздела
4соответствие, которое говорит:[...]Неопределенное поведение в противном случае указывается в настоящем международном стандарте словами "неопределенное поведение" или отсутствие четкого определения поведение.[...]
мы также можем посмотреть на C99 обоснование он говорит:
набор символов, необходимых для сохранения в текстовом потоке ввода / вывода, необходимы для записи C программы; цель состоит в том, что стандарт должен позволять переводчику C быть написанным в максимально портативный мода. Управляющие символы, такие как backspace, не требуются для этой цели, поэтому их обработка текстовых потоков не уполномоченный.
cout<<"\n"[a==N];я понятия не имею о том, что делает опция [] в cout
на таблица приоритета операторов C++,
operator []связывает крепче, чемoperator <<, так что ваш код эквивалентен:cout << ("\n"[a==N]); // or cout.operator <<("\n"[a==N]);или другими словами,
operator []ничего не делает напрямую сcout. Он используется только для индексации строкового литерала"\n"for(int i = 0; i < 3; ++i) std::cout << "abcdef"[i] << std::endl;напечатает характеры a, b и c на последовательных строках на экран.
, потому что строковые литералы на
C++are всегда завершается символом null('',L'',char16_t(), etc), строковый литерал"\n"этоconst char[2]держа символы'\n'и''в макете памяти это выглядит так:
+--------+--------+ | '\n' | '' | +--------+--------+ 0 1 <-- Offset false true <-- Result of condition (a == n) a != n a == n <-- Caseтак что если
a == Nверно (повышено до 1), выражение"\n"[a == N]результаты''и'\n'если результат ложный.он функционально похож (не то же самое) на:
char anonymous[] = "\n"; int index; if (a == N) index = 1; else index = 0; cout << anonymous[index];valueof
"\n"[a==N]и'\n'или''typeof
"\n"[a==N]иconst char
если намерение состоит в том, чтобы ничего не печатать (что может отличаться от печати
''в зависимости от платформы и назначения), предпочитают следующую строку кода:if(a != N) cout << '\n';даже если ваше намерение состоит в том, чтобы написать
''или'\n'на поток, предпочитаю читаемый код например:cout << (a == N ? '' : '\n');
это, вероятно, задумано как причудливый способ написания
if ( a != N ) { cout<<"\n"; }The
[]оператор выбирает элемент из массива. Строка"\n"на самом деле массив из двух символов: новую строку'\n'и признак конца строки''. Так чтоcout<<"\n"[a==N]выведет либо a'\n'символ или''символ.беда в том, что вы не можете отправить
''символ в поток ввода/вывода в текстовом режиме. Автор этого кода, возможно, заметил казалось, что ничего не происходит, поэтому он предположил, чтоcout<<''- это надежный способ ничего не делать.в C и C++ это очень плохое предположение из-за понятия неопределенное поведение. если программа делает что-то, что не охватывается спецификацией стандарта или конкретной платформы, все может произойти. Довольно вероятным результатом в этом случае является то, что поток полностью перестанет работать - больше не выводится на
coutпоявится в все.таким образом, эффект,
" вывести новую строку, если
aне равноN. В противном случае, я не знаю. Авария или что-то в этом роде."... и мораль в том, чтобы не писать вещи так загадочно.
это не вариант
coutно индекс массива"\n"индекс массива
[a==N]вычисляет значение [0] или [1] и индексирует массив символов, представленный"\n"который содержит новую строку и символ nul.однако передача nul в iostream будет иметь неопределенные результаты, и было бы лучше передать строку:
cout << &("\n"[a==N]) ;однако код в любом случае не является особенно целесообразным и не служит никакой конкретной цели, кроме чтобы запутать; не рассматривайте это как пример хорошей практики. В большинстве случаев предпочтительно следующее:
cout << (a != N ? "\n" : "") ;или так:
if( a != N ) cout << `\n` ;
каждая из следующих строк будет генерировать точно такой же выход:
cout << "\n"[a==N]; // Never do this. cout << (a==N)["\n"]; // Or this. cout << *((a==N)+"\n"); // Or this. cout << *("\n"+(a==N)); // Or this.
Как указано в других ответах, это не имеет ничего общего сstd::cout. Это вместо этого является следствием
как реализуется примитивный (не перегруженный) оператор подписки в C и c++.
На обоих языках, еслиarray- это массив примитивов в стиле C,array[42]- это синтаксический сахар для*(array+42). Хуже того, нет никакой разницы междуarray+42и42+array. Это приводит к интересному запутыванию: Use42[array]вместоarray[42]Если ваша цель состоит в том, чтобы полностью запутать ваш код. Само собой разумеется, что писать!--7--> это ужасная идея, если ваша цель-написать понятный, поддерживаемый код.как булевы преобразуются в целые числа.
Дано выражение видаa[b], либоaилиbдолжно быть выражение указателя и другое; другое должно быть целочисленное выражение. Учитывая выражение"\n"[a==N]на"\n"представляет часть указателя этого выражения иa==Nобозначает целую часть выражения. Вот,a==N- это логическое выражение,falseилиtrue. Целочисленные правила продвижения указывают, чтоfalseстановится 0 иtrueстановится 1 при продвижении к целому числу.как строковые литералы деградируют в указатели.
Когда указатель необходим, массивы в C и C++ легко деградировать в указатель, который указывает на первый элемент массива.как реализуются строковые литералы.
Каждый строковый литерал C-стиля добавляется с нулевым символом''. Это означает внутреннее представление вашего"\n"массив{'\n', ''}.
Учитывая вышесказанное, предположимa==Nоценивает вfalse. В этом случае поведение четко определено во всех системах: Вы получите новую строку. Если, с другой стороны,a==Nоценивает вtrueповедение сильно зависит от системы. Судя по комментариям к ответам на вопрос, Windows это не понравится. На UNIX-подобных системах, гдеstd::coutпередается в окно терминала, поведение довольно мягкое. Ничего не происходит.
Просто потому, что вы можете написать такой код, это не значит, что вы должны. Никогда не пишите такой код.
Comments