что в cout



в следующем примере:



cout<<"n"[a==N];


Я понятия не имею о том, что и в cout, но он не печатает новую строку, если значение a равна N.

527   5  

5 ответов:

я понятия не имею о том, что делает опция [] в cout

это на самом деле не cout вариант, что происходит это "\n" это строковый литерал. Строковый литерал имеет тип массив N const char на [] - это просто индекс в массив символов, который в данном случае содержит:

\n

Примечание добавляется ко всем строковым литералам.

в == оператор приводит или правда или ложные, так что индекс будет:

  • 0 если false, если a Не равно N в результате \n
  • 1 если 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. Это приводит к интересному запутыванию: Use 42[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

    Ничего не найдено.