cout<<"\n"[a==N];
我不知道在cout
中使用[]
选项是什么意思,但当a
的值等于N
时,它不会打印换行符。
cout<<"\n"[a==N];
我不知道在cout
中使用[]
选项是什么意思,但当a
的值等于N
时,它不会打印换行符。
"\n"
是一个字符串字面量。字符串字面量的类型为n个const char的数组,[]
只是一个字符数组中的索引,在本例中它包含了:\n\0
\0
。
==
运算符的结果要么是 true,要么是 false,因此索引将为:
a
不等于 N
,结果为 \n
,则索引为 0
a
等于 N
,结果为 \0
,则索引为 1
if
语句代替。2.14.5
节 字符串字面值 [lex.string] 中指出(重点标出):
字符串字面值的类型为“长度为n的const char数组”,其中n是下面定义的字符串大小,并具有静态存储期(3.7)。
并且:
在必要的连接后,在第7个翻译阶段(2.2)中,会在每个字符串字面值后添加'\0',以便扫描字符串的程序可以找到其结尾。
第4.5
节 [conv.prom] 表示:
bool类型的prvalue可以转换为int类型的prvalue,其中false变成零,true变成一。
将空字符写入文本流
声称在文本流中写入空字符(\0
)是未定义行为。
就我所知,这是一个合理的结论,因为我们可以从27.4.2
[narrow.stream.objects]中看到,cout
是根据C流定义的。
在C++运算符优先级表中,
cout<<"\n"[a==N];
I have no clue about what the [] option does in cout
operator []
比operator <<
的优先级更高,因此您的代码等同于:cout << ("\n"[a==N]); // or cout.operator <<("\n"[a==N]);
< p>换句话说, operator []
不会直接影响 cout
。它仅用于字符串文字"\ n"
的索引。
例如, for(int i = 0; i<3; ++i)std :: cout <<“ abcdef” [i] << std :: endl;
将在屏幕上连续打印字符a,b和c。
'\0'
,L'\0'
,char16_t()
等)结尾,所以字符串字面值"\n"
是一个包含字符'\n'
和'\0'
的const char[2]
。+--------+--------+
| '\n' | '\0' |
+--------+--------+
0 1 <-- Offset
false true <-- Result of condition (a == n)
a != n a == n <-- Case
a == N
为真(转换为1),则表达式"\n"[a == N]
的结果为'\0'
,如果结果为假,则为'\n'
。char anonymous[] = "\n";
int index;
if (a == N) index = 1;
else index = 0;
cout << anonymous[index];
"\n"[a==N]
的值为 '\n'
或 '\0'
"\n"[a==N]
的类型为 const char
'\0'
),请使用以下代码行:if(a != N) cout << '\n';
'\0'
或'\n'
,也应该优先选择可读性更好的代码,例如:即使你的意图是在流中写入'\0'
或'\n'
,请优先使用易于阅读的代码,例如:
cout << (a == N ? '\0' : '\n');
这可能是一种奇怪的书写方式。
这段话与IT技术无关。if ( a != N ) {
cout<<"\n";
}
[]
操作符从数组中选择一个元素。字符串 "\n"
实际上是由两个字符组成的数组:一个换行符 '\n'
和一个字符串终止符 '\0'
。因此,cout<<"\n"[a==N]
将打印一个 '\n'
字符或一个 '\0'
字符。'\0'
字符发送到 I/O 流中。那段代码的作者可能已经注意到似乎什么也没发生,所以他认为 cout<<'\0'
是一种安全的方法什么都不做。cout
。…所以,教训是,不要写得那么难懂。“如果
a
不等于N
,则打印一个换行符。否则,我不知道。崩溃或其他什么。”
int
的大小没有定义,但这使其成为未指定的。 - MSalters'\0'
到std::cout
是否是未定义行为。根据我对标准的阅读,它不是。仅仅因为Windows在这方面做了一些不同的事情,并不意味着它是UB。这只是意味着Windows再次做了一些不同的事情。 - David Hammen这不是cout
的一个选项,而是"\n"
的一个数组索引。
数组索引[a==N]
的值为[0]或[1],并索引由"\n"
表示的字符数组,其中包含换行符和空字符。
然而将空字符传递给iostream会导致未定义的结果,最好传递一个字符串:
cout << &("\n"[a==N]) ;
然而,这两种情况下的代码都不是特别可取的,除了混淆之外没有任何特别的目的;不要把它视为良好实践的例子。在大多数情况下,以下做法更可取:
cout << (a != N ? "\n" : "") ;
if( a != N ) cout << `\n` ;
cout << &"\n"[a==N]
。 - eush77每个以下的语句都会产生完全相同的输出:
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风格的字符串字面值都以空字符'\0'
结尾。这意味着你的"\n"
的内部表示形式是数组{'\n', '\0'}
。
鉴于上述情况,假设a==N
评估为false
。在这种情况下,所有系统的行为都是定义良好的:你会得到一个换行符。另一方面,如果a==N
评估为true
,则行为高度依赖于系统。根据问题答案的评论,在Windows系统中,这段代码不会工作。在将std::cout
管道传输到终端窗口的类Unix系统中,行为相对温和。什么都不会发生。
仅仅因为你可以编写这样的代码并不意味着你应该这样做。永远不要编写这样的代码。
'\0'
到输出,这在Unix和Linux机器上是完全可以的。这种情况经常发生。二进制模式,文本模式?那是什么?Unix和Linux不区分这两者。C和C++标准的某些部分向Windows屈服,其他部分向Unix和Linux屈服,还有其他部分向其他架构屈服。不要太以Windows为中心。 - David Hammen*
。抱歉。 - Mark Hurd*
,它将更适用于所有环境 :-) - Mark Hurd*
会导致 clang 发出一个愚蠢的警告。我必须使用 Wno-string-int
编译才能使其编译干净。在前两个语句中添加一个 ampersand 有相同的效果,即使没有该编译器选项也可以编译干净,并且它还具有增加混淆级别的附加好处。(显然,gnu 的 binutils 从 "some_string"+some_int
修改为 &"some_string"[some_int]
,因为这个编译器警告。) - David Hammen
""
。 - IMSoPcout << '\0'
的效果是什么。 - M.M