In the following example:
cout<<"\n"[a==N];
I have no clue about what the []
option does in cout
, but it does not print a newline when the value of a
is equal to N
.
In the following example:
cout<<"\n"[a==N];
I have no clue about what the []
option does in cout
, but it does not print a newline when the value of a
is equal to N
.
Each of the following lines will generate exactly the same output:
As the other answers have specified, this has nothing to do with
std::cout
. It instead is a consequence ofHow the primitive (non-overloaded) subscripting operator is implemented in C and C++.
In both languages, if
array
is a C-style array of primitives,array[42]
is syntactic sugar for*(array+42)
. Even worse, there's no difference betweenarray+42
and42+array
. This leads to interesting obfuscation: Use42[array]
instead ofarray[42]
if your goal is to utterly obfuscate your code. It goes without saying that writing42[array]
is a terrible idea if your goal is to write understandable, maintainable code.How booleans are transformed to integers.
Given an expression of the form
a[b]
, eithera
orb
must be a pointer expression and the other; the other must be an integer expression. Given the expression"\n"[a==N]
, the"\n"
represents the pointer part of that expression and thea==N
represents the integer part of the expression. Here,a==N
is a boolean expression that evaluates tofalse
ortrue
. The integer promotion rules specify thatfalse
becomes 0 andtrue
becomes 1 on promotion to an integer.How string literals degrade into pointers.
When a pointer is needed, arrays in C and C++ readily degrade into a pointer that points to the first element of the array.
How string literals are implemented.
Every C-style string literal is appended with the null character
'\0'
. This means the internal representation of your"\n"
is the array{'\n', '\0'}
.Given the above, suppose
a==N
evaluates tofalse
. In this case, the behavior is well-defined across all systems: You'll get a newline. If, on the other hand,a==N
evaluates totrue
, the behavior is highly system dependent. Based on comments to answers to the question, Windows will not like that. On Unix-like systems wherestd::cout
is piped to the terminal window, the behavior is rather benign. Nothing happens.Just because you can write code like that doesn't mean you should. Never write code like that.
In C++ operator Precedence table,
operator []
binds tighter thanoperator <<
, so your code is equivalent to:Or in other words,
operator []
does nothing directly withcout
. It is used only for indexing of string literal"\n"
For example
for(int i = 0; i < 3; ++i) std::cout << "abcdef"[i] << std::endl;
will print characters a, b and c on consecutive lines on the screen.Because string literals in
C++
are always terminated with null character('\0'
,L'\0'
,char16_t()
, etc), a string literal"\n"
is aconst char[2]
holding the characters'\n'
and'\0'
In memory layout this looks like:
So if
a == N
is true (promoted to 1), expression"\n"[a == N]
results in'\0'
and'\n'
if result is false.It is functionally similar (not same) to:
valueof
"\n"[a==N]
is'\n'
or'\0'
typeof
"\n"[a==N]
isconst char
If the intention is to print nothing (Which may be different from printing
'\0'
depending on platform and purpose), prefer the following line of code:Even if your intention is to write either
'\0'
or'\n'
on the stream, prefer a readable code for example:It's probably intended as a bizarre way of writing
The
[]
operator selects an element from an array. The string"\n"
is actually an array of two characters: a new line'\n'
and a string terminator'\0'
. Socout<<"\n"[a==N]
will print either a'\n'
character or a'\0'
character.The trouble is that you're not allowed to send a
'\0'
character to an I/O stream in text mode. The author of that code might have noticed that nothing seemed to happen, so he assumed thatcout<<'\0'
is a safe way to do nothing.In C and C++, that is a very poor assumption because of the notion of undefined behavior. If the program does something that is not covered by the specification of the standard or the particular platform, anything can happen. A fairly likely outcome in this case is that the stream will stop working entirely — no more output to
cout
will appear at all.In summary, the effect is,
… and the moral is, don't write things so cryptically.
It is not an option of
cout
but an array index of"\n"
The array index
[a==N]
evaluates to [0] or [1], and indexes the character array represented by"\n"
which contains a newline and a nul character.However passing nul to the iostream will have undefined results, and it would be better to pass a string:
However, the code in either case is not particularly advisable and serves no particular purpose other than to obfuscate; do not regard it as an example of good practice. The following is preferable in most instances:
or just:
This is actually not a
cout
option, what is happening is that"\n"
is a string literal. A string literal has the type array of n const char, the[]
is simply an index into an array of characters which in this case contains:note
\0
is appended to all string literals.The
==
operator results in either true or false, so the index will be:0
if false, ifa
does not equalN
resulting in\n
1
if true, ifa
equalsN
resulting in\0
This is rather cryptic and could have been replaced with a simple
if
.For reference the C++14 standard(Lightness confirmed the draft matches the actual standard) with the closest draft being N3936 in section
2.14.5
String literals [lex.string] says (emphasis mine):and:
section
4.5
[conv.prom] says:Writing a null character to a text stream
The claim was made that writing a null character(
\0
) to a text stream is undefined behavior.As far as I can tell this is a reasonable conclusion,
cout
is defined in terms of C stream, as we can see from27.4.2
[narrow.stream.objects] which says:and the C11 draft standard in section
7.21.2
Streams says:and printing characters are covered in
7.4
Character handling <ctype.h>:with footnote
199
saying:and finally we can see that the result of sending a null character is not specified and we can see this is undefined behavior from section
4
Conformance which says:We can also look to the C99 rationale which says: