cout << "\n"[a==N]; 是什么意思?做?
what does cout << "\n"[a==N]; do?
在下面的例子中:
cout<<"\n"[a==N];
我不知道 []
选项在 cout
中的作用,但是当 a
的值等于 N
时它不会打印换行符.
cout<<"\n"[a==N];
I have no clue about what the [] option does in cout
在 C++ operator Precedence table 中,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++
中的 string literals 总是 以空字符结尾('[=23=]'
, L'[=24=]'
, char16_t()
, 等), 字符串文字 "\n"
是 const char[2]
包含字符 '\n'
和 '[=23=]'
在内存布局中如下所示:
+--------+--------+
| '\n' | '[=12=]' |
+--------+--------+
0 1 <-- Offset
false true <-- Result of condition (a == n)
a != n a == n <-- Case
因此,如果 a == N
为真(提升为 1),表达式 "\n"[a == N]
结果为 '[=23=]'
,如果结果为假,则为 '\n'
。
它在功能上类似于(不相同):
char anonymous[] = "\n";
int index;
if (a == N) index = 1;
else index = 0;
cout << anonymous[index];
"\n"[a==N]
的值是 '\n'
或 '[=23=]'
typeof "\n"[a==N]
是 const char
如果打算什么都不打印(这可能与打印 '[=23=]'
不同,具体取决于平台和目的),请使用以下代码行:
if(a != N) cout << '\n';
即使你的意图是在流上写'[=23=]'
或'\n'
,最好是可读的代码,例如:
cout << (a == N ? '[=15=]' : '\n');
这可能是一种奇怪的写作方式
if ( a != N ) {
cout<<"\n";
}
[]
运算符从数组中选择一个元素。字符串 "\n"
实际上是一个包含两个字符的数组:换行符 '\n'
和字符串终止符 '[=14=]'
。所以 cout<<"\n"[a==N]
将打印 '\n'
个字符或 '[=14=]'
个字符。
问题是您不能在文本模式下将 '[=14=]'
字符发送到 I/O 流。该代码的作者可能已经注意到似乎什么都没发生,所以他认为 cout<<'[=19=]'
是一种什么都不做的安全方法。
在 C 和 C++ 中,由于 未定义行为的概念,这是一个非常糟糕的假设。 如果程序执行标准规范或未涵盖的操作特定的平台,任何事情都有可能发生。在这种情况下,一个很可能的结果是流将完全停止工作——根本不会出现 cout
的输出。
综上所述,效果是,
"Print a newline if a
is not equal to N
. Otherwise, I don't know. Crash or something."
…道德是,不要写得那么隐晦。
不是cout
的选项而是"\n"
的数组索引
数组索引[a==N]
的计算结果为[0]或[1],并索引由"\n"
表示的包含换行符和空字符的字符数组。
然而将 nul 传递给 iostream 将得到未定义的结果,传递一个字符串会更好:
cout << &("\n"[a==N]) ;
但是,这两种情况下的代码都不是特别可取的,并且除了混淆之外没有任何特殊目的;不要将其视为良好实践的范例。在大多数情况下,以下内容更可取:
cout << (a != N ? "\n" : "") ;
或者只是:
if( a != N ) cout << `\n` ;
I have no clue about what the [] option does in cout
这实际上不是 cout
选项,实际情况是 "\n"
是 string literal。字符串文字的类型为 array of n const char,[]
只是字符数组的索引,在本例中包含:
\n[=10=]
注意 [=14=]
附加到所有字符串文字。
==
运算符结果为 true 或 false,因此索引将为:
0
如果为假,如果 a
不等于 N
导致 \n
1
如果为真,如果 a
等于 N
导致 [=14=]
这相当神秘,可以用简单的 if
代替。
参考C++14标准(Lightness确认草案符合实际标准)最接近的草案是N3936部分2.14.5
字符串文字 [lex.string] 说(强调我的):
string literal has type “array of n const char”, where n is the
size of the string as defined below, and has static storage duration
(3.7).
和:
After any necessary concatenation, in translation phase 7 (2.2),
’[=36=]’ is appended to every string literal so that programs that scan a string can find its end.
部分 4.5
[conv.prom] 说:
A prvalue of type bool can be converted to a prvalue of type int, with
false becoming zero and true becoming one.
将空字符写入文本流
声称将空字符 ([=14=]
) 写入文本流是未定义的行为。
据我所知这是一个合理的结论,cout
是根据C流定义的,从27.4.2
[narrow.stream.objects] 表示:
The object cout controls output to a stream buffer associated with the object stdout, declared in
<cstdio> (27.9.2).
和 7.21.2
Streams 部分的 C11 标准草案说:
[...]Data read in from a text stream will necessarily compare equal to the data
that were earlier written out to that stream only if: the data consist only of printing
characters and the control characters horizontal tab and new-line;
和打印字符包含在7.4
字符处理 :
[...]the term control character
refers to a member of a locale-specific set of characters that are not printing
characters.199) All letters and digits are printing characters.
带脚注 199
说:
In an implementation that uses the seven-bit US ASCII character set, the printing characters are those
whose values lie from 0x20 (space) through 0x7E (tilde); the control characters are those whose
values lie from 0 (NUL) through 0x1F (US), and the character 0x7F (DEL).
最后我们可以看到未指定发送空字符的结果,我们可以从 4
一致性部分看到这是未定义的行为,它说:
[...]Undefined behavior is otherwise
indicated in this International Standard by the words ‘‘undefined behavior’’ or by the
omission of any explicit definition of behavior.[...]
我们还可以查看 C99 rationale 上面写着:
The set of characters required to be preserved in text stream I/O are those needed for writing C
programs; the intent is that the Standard should permit a C translator to be written in a maximally
portable fashion. Control characters such as backspace are not required for this purpose, so their
handling in text streams is not mandated.
以下每一行都将生成完全相同的输出:
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
之间没有区别。这会导致有趣的混淆:如果您的目标是完全混淆您的代码,请使用 42[array]
而不是 array[42]
。不用说,如果您的目标是编写可理解、可维护的代码,那么编写 42[array]
是一个糟糕的主意。
布尔值如何转换为整数。
给定 a[b]
形式的表达式,a
或 b
必须是指针表达式,另一个必须是;另一个必须是整数表达式。给定表达式 "\n"[a==N]
,"\n"
表示该表达式的指针部分,a==N
表示表达式的整数部分。这里,a==N
是一个布尔表达式,计算结果为 false
或 true
。整数提升规则指定 false
在提升为整数时变为 0,而 true
变为 1。
字符串文字如何退化为指针。
当需要指针时,C 和 C++ 中的数组很容易退化为指向数组第一个元素的指针。
如何实现字符串文字。
每个 C 风格的字符串文字都附加了空字符 '[=31=]'
。这意味着 "\n"
的内部表示是数组 {'\n', '[=33=]'}
.
鉴于上述情况,假设 a==N
的计算结果为 false
。在这种情况下,行为在所有系统中都是明确定义的:您将得到一个换行符。另一方面,如果 a==N
的计算结果为 true
,则该行为高度依赖于系统。根据对问题答案的评论,Windows 不会这样。在 std::cout
被管道传输到终端 window 的类 Unix 系统上,行为是相当良性的。没有任何反应。
仅仅因为您可以编写这样的代码并不意味着您应该这样做。永远不要写那样的代码。
在下面的例子中:
cout<<"\n"[a==N];
我不知道 []
选项在 cout
中的作用,但是当 a
的值等于 N
时它不会打印换行符.
cout<<"\n"[a==N];
I have no clue about what the [] option does in cout
在 C++ operator Precedence table 中,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++
中的 string literals 总是 以空字符结尾('[=23=]'
, L'[=24=]'
, char16_t()
, 等), 字符串文字 "\n"
是 const char[2]
包含字符 '\n'
和 '[=23=]'
在内存布局中如下所示:
+--------+--------+
| '\n' | '[=12=]' |
+--------+--------+
0 1 <-- Offset
false true <-- Result of condition (a == n)
a != n a == n <-- Case
因此,如果 a == N
为真(提升为 1),表达式 "\n"[a == N]
结果为 '[=23=]'
,如果结果为假,则为 '\n'
。
它在功能上类似于(不相同):
char anonymous[] = "\n";
int index;
if (a == N) index = 1;
else index = 0;
cout << anonymous[index];
"\n"[a==N]
的值是 '\n'
或 '[=23=]'
typeof "\n"[a==N]
是 const char
如果打算什么都不打印(这可能与打印 '[=23=]'
不同,具体取决于平台和目的),请使用以下代码行:
if(a != N) cout << '\n';
即使你的意图是在流上写'[=23=]'
或'\n'
,最好是可读的代码,例如:
cout << (a == N ? '[=15=]' : '\n');
这可能是一种奇怪的写作方式
if ( a != N ) {
cout<<"\n";
}
[]
运算符从数组中选择一个元素。字符串 "\n"
实际上是一个包含两个字符的数组:换行符 '\n'
和字符串终止符 '[=14=]'
。所以 cout<<"\n"[a==N]
将打印 '\n'
个字符或 '[=14=]'
个字符。
问题是您不能在文本模式下将 '[=14=]'
字符发送到 I/O 流。该代码的作者可能已经注意到似乎什么都没发生,所以他认为 cout<<'[=19=]'
是一种什么都不做的安全方法。
在 C 和 C++ 中,由于 未定义行为的概念,这是一个非常糟糕的假设。 如果程序执行标准规范或未涵盖的操作特定的平台,任何事情都有可能发生。在这种情况下,一个很可能的结果是流将完全停止工作——根本不会出现 cout
的输出。
综上所述,效果是,
"Print a newline if
a
is not equal toN
. Otherwise, I don't know. Crash or something."
…道德是,不要写得那么隐晦。
不是cout
的选项而是"\n"
数组索引[a==N]
的计算结果为[0]或[1],并索引由"\n"
表示的包含换行符和空字符的字符数组。
然而将 nul 传递给 iostream 将得到未定义的结果,传递一个字符串会更好:
cout << &("\n"[a==N]) ;
但是,这两种情况下的代码都不是特别可取的,并且除了混淆之外没有任何特殊目的;不要将其视为良好实践的范例。在大多数情况下,以下内容更可取:
cout << (a != N ? "\n" : "") ;
或者只是:
if( a != N ) cout << `\n` ;
I have no clue about what the [] option does in cout
这实际上不是 cout
选项,实际情况是 "\n"
是 string literal。字符串文字的类型为 array of n const char,[]
只是字符数组的索引,在本例中包含:
\n[=10=]
注意 [=14=]
附加到所有字符串文字。
==
运算符结果为 true 或 false,因此索引将为:
0
如果为假,如果a
不等于N
导致\n
1
如果为真,如果a
等于N
导致[=14=]
这相当神秘,可以用简单的 if
代替。
参考C++14标准(Lightness确认草案符合实际标准)最接近的草案是N3936部分2.14.5
字符串文字 [lex.string] 说(强调我的):
string literal has type “array of n const char”, where n is the size of the string as defined below, and has static storage duration (3.7).
和:
After any necessary concatenation, in translation phase 7 (2.2), ’[=36=]’ is appended to every string literal so that programs that scan a string can find its end.
部分 4.5
[conv.prom] 说:
A prvalue of type bool can be converted to a prvalue of type int, with false becoming zero and true becoming one.
将空字符写入文本流
声称将空字符 ([=14=]
) 写入文本流是未定义的行为。
据我所知这是一个合理的结论,cout
是根据C流定义的,从27.4.2
[narrow.stream.objects] 表示:
The object cout controls output to a stream buffer associated with the object stdout, declared in <cstdio> (27.9.2).
和 7.21.2
Streams 部分的 C11 标准草案说:
[...]Data read in from a text stream will necessarily compare equal to the data that were earlier written out to that stream only if: the data consist only of printing characters and the control characters horizontal tab and new-line;
和打印字符包含在7.4
字符处理
[...]the term control character refers to a member of a locale-specific set of characters that are not printing characters.199) All letters and digits are printing characters.
带脚注 199
说:
In an implementation that uses the seven-bit US ASCII character set, the printing characters are those whose values lie from 0x20 (space) through 0x7E (tilde); the control characters are those whose values lie from 0 (NUL) through 0x1F (US), and the character 0x7F (DEL).
最后我们可以看到未指定发送空字符的结果,我们可以从 4
一致性部分看到这是未定义的行为,它说:
[...]Undefined behavior is otherwise indicated in this International Standard by the words ‘‘undefined behavior’’ or by the omission of any explicit definition of behavior.[...]
我们还可以查看 C99 rationale 上面写着:
The set of characters required to be preserved in text stream I/O are those needed for writing C programs; the intent is that the Standard should permit a C translator to be written in a maximally portable fashion. Control characters such as backspace are not required for this purpose, so their handling in text streams is not mandated.
以下每一行都将生成完全相同的输出:
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
之间没有区别。这会导致有趣的混淆:如果您的目标是完全混淆您的代码,请使用42[array]
而不是array[42]
。不用说,如果您的目标是编写可理解、可维护的代码,那么编写42[array]
是一个糟糕的主意。布尔值如何转换为整数。
给定a[b]
形式的表达式,a
或b
必须是指针表达式,另一个必须是;另一个必须是整数表达式。给定表达式"\n"[a==N]
,"\n"
表示该表达式的指针部分,a==N
表示表达式的整数部分。这里,a==N
是一个布尔表达式,计算结果为false
或true
。整数提升规则指定false
在提升为整数时变为 0,而true
变为 1。字符串文字如何退化为指针。
当需要指针时,C 和 C++ 中的数组很容易退化为指向数组第一个元素的指针。如何实现字符串文字。
每个 C 风格的字符串文字都附加了空字符'[=31=]'
。这意味着"\n"
的内部表示是数组{'\n', '[=33=]'}
.
鉴于上述情况,假设 a==N
的计算结果为 false
。在这种情况下,行为在所有系统中都是明确定义的:您将得到一个换行符。另一方面,如果 a==N
的计算结果为 true
,则该行为高度依赖于系统。根据对问题答案的评论,Windows 不会这样。在 std::cout
被管道传输到终端 window 的类 Unix 系统上,行为是相当良性的。没有任何反应。
仅仅因为您可以编写这样的代码并不意味着您应该这样做。永远不要写那样的代码。