在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(++)程序,其数据常量为“command”,例如void main() {0; 'a'; "foobar"; false;}
。它是seems to be a sort of nop command,但我无法找到有关此类用法的任何信息 - Google isn’t very amenable to this type of search {{3 }})。
任何人都可以准确解释它是什么以及它是如何工作的吗?
答案 0 :(得分:5)
在C和C ++中,可以通过将;
放在最后来将任何表达式转换为语句。
另一个例子是表达式x = 5
可以成为一个语句:x = 5;
。希望你同意这是一个好主意。
语言会不必要地使语言变得复杂,试图“禁止”某些表达式子集使;
跟在它们之后。此代码不是很有用,但它是合法的。
答案 1 :(得分:2)
请注意,您链接的代码是糟糕并由一个非常糟糕的程序员编写。特别是声明
"微型C程序中常见的做法是定义重用的表达式 使代码更小"
完成了b *** s ***。这句话就是事情开始变得非常糟糕的地方。
源代码的大小与编译器可执行文件的大小无关,也与该可执行文件的内存消耗无关,也与程序性能无关。它唯一影响的是程序员计算机上源代码文件的大小,用 bytes 表示。
除非你在80年代中期使用非常有限的硬盘空间对8086计算机进行编程,否则你永远不需要减少代码的大小"。相反,写出可读代码。
话虽如此,由于classpath 'com.android.tools.build:gradle-experimental:0.2.1'
是一个字符数组,您链接的代码相当于
q
if(q[11])
{
(int)(q[3] |= 4);
}
else
{
1;
}
是一个没有副作用的陈述,它将被优化掉。它只放在那里,因为1
运算符需要第三个运算符。
if语句和?:
运算符之间的唯一区别是微妙的:?:
隐式平衡第2和第3个操作数之间的类型。
为了提高可读性并生成自我记录代码,代码应该被重写为
?:
作为旁注,这里有一个错误:if (q[AR_INDEX] != 0)
{
q[REPLY_INDEX] |= NOT_IMPLEMENTED;
}
。 q[2]|=128;
的类型为char,它具有实现定义的签名,因此该行可能是灾难性的。核心问题是你永远不应该使用q
类型进行逐位操作或任何形式的算术,这是一个典型的初学者错误。必须将其替换为char
或uint8_t
。