三元运算符作为命令?

Ternary operator as a command?

source-code for nanodns中,有一个非典型的使用三元运算符试图减少代码的大小:

/* If the incoming packet has an AR record (such as in an EDNS request),
 * mark the reply as "NOT IMPLEMENTED"; using a?b:c form to save one byte*/
q[11]?q[3]|=4:1;

这一行的作用不明显。乍一看,好像是在给两个数组元素之一赋值,其实不然。相反,它似乎要么是一个数组元素,要么什么都不做(运行宁“命令”1)。

看起来应该是这行代码的替代品(确实长了一个字节):

if(q[11])q[3]|=4;

字面上的等价物是这样的:

if (q[11])
  q[3]|=4;
else
  1;

三元运算符通常用作表达式的一部分,因此将其用作独立命令似乎很奇怪。再加上看似格格不入的1,这一行几乎可以算是混淆码了

我做了一个快速测试,并且能够编译 运行 一个 C(++) 程序,其中数据常量作为“命令”,例如 void main() {0; 'a'; "foobar"; false;}。它 seems to be a sort of nop command, but I cannot find any information about such usage—Google isn’t very amenable to this type of search query).

谁能准确解释它是什么以及它是如何工作的?

在 C 和 C++ 中,任何表达式都可以通过在末尾添加 ; 来构成语句。

另一个例子是表达式 x = 5 可以变成语句: x = 5; 。希望您同意这是个好主意。

尝试 "ban" 表达式的某些子集后 ; 会使语言不必要地复杂化。此代码不是很有用,但它是合法的。

请注意,您链接到的代码 很糟糕 并且是由一个非常糟糕的程序员编写的。特别是声明

"It is common practice in tiny C programs to define reused expressions to make the code smaller"

完成 b***s***。这句话是事情开始变得非常错误的地方。

源代码的大小与编译器可执行文件的大小无关,与可执行文件的内存消耗无关,与程序性能也无关。它唯一影响的是程序员计算机上源代码文件的大小,以字节.

表示

除非你在 80 年代中期的一些 8086 计算机上编程,硬盘非常有限 space,否则你永远不需要 "reduce the size of the code"。相反,编写可读代码。

也就是说,由于 q 是一个字符数组,您链接的代码等同于

if(q[11])
{
  (int)(q[3] |= 4);
}
else
{
  1;
}

其中 1 是没有副作用的语句,它将被优化掉。之所以放在那里,是因为 ?: 运算符需要第三个运算符。

if 语句和 ?: 运算符之间的唯一区别是微妙的:?: 隐式地平衡了第二个和第三个操作数之间的类型。

为了提高可读性并生成自文档化代码,代码应该重写为

if (q[AR_INDEX] != 0)
{
  q[REPLY_INDEX] |= NOT_IMPLEMENTED;
}

附带说明一下,这里有一个错误:q[2]|=128;q 是 char 类型,它具有实现定义的符号,所以这一行可能是灾难性的。核心问题是您永远不应该将 char 类型用于按位运算或任何形式的算术,这是一个典型的初学者错误。它必须替换为 uint8_tunsigned char.