作为命令的三元操作符
Ternary operator as a command?
在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;}
。这似乎是一种nop命令,但我找不到任何关于这种用法的信息(谷歌不太支持这种类型的搜索查询)。
谁能确切地解释一下它是什么以及它是如何工作的?
在C和c++中,只要把;
放在末尾,任何表达式都可以构成一个语句。
另一个例子是表达式x = 5
可以做成一个语句:x = 5;
。希望你同意这是个好主意。
如果试图"禁止"某些表达式子集后面出现;
,这将不必要地使语言复杂化。这个代码不是很有用,但它是合法的。
请注意,您链接到的代码非常糟糕,并且是由一个非常糟糕的程序员编写的。特别是,语句
"在小型C程序中定义重用表达式是常见的做法使代码更小"
是完整的b***s***。这句话就是事情开始变得非常糟糕的地方。
源代码的大小与编译器可执行文件的大小没有关系,与可执行文件的内存消耗也没有关系,与程序性能也没有关系。它唯一影响的是程序员计算机上源代码文件的大小,用字节表示。
除非你是在80年代中期的8086计算机上编程,硬盘空间非常有限,否则你永远不需要"减少代码的大小"。相反,编写可读的代码。
话虽如此,由于q
是一个字符数组,因此您链接的代码相当于
if(q[11])
{
(int)(q[3] |= 4);
}
else
{
1;
}
其中1
是一个没有副作用的语句,它将被优化掉。它被放在那里只是因为?:
运算符需要第三个运算符。
?:
操作符之间的唯一区别是微妙的:?:
隐式地平衡了第二个和第三个操作数之间的类型。为了提高可读性和生成自文档代码,应该将代码重写为类似
的内容。if (q[AR_INDEX] != 0)
{
q[REPLY_INDEX] |= NOT_IMPLEMENTED;
}
作为旁注,这里有一个错误:q[2]|=128;
。q
是char类型,它具有实现定义的签名,因此这一行可能是灾难性的。核心问题是,您永远不应该将char
类型用于位操作或任何形式的算术,这是典型的初学者错误。必须替换为uint8_t
或unsigned char
- 如何编写一个使用n倍三元条件语句的C++布尔函数
- 三元运算符和 if constexpr
- 在 c++ 中三元运算符中不允许继续(关键字)吗?
- 三元运算符在返回语句中给出意外的结果
- Boost Spirit x3 条件(三元)运算符解析器
- 为什么用三元初始化类会导致双重释放?
- 如何有效地找到数组中三元组和的最小差异?
- 递归中三元运算符的奇怪行为
- 如何在三元条件运算符中添加换行符和连接? :在 C++ 中
- 错误:三元运算符无法在对象中正常工作"cout"
- 如何重写复杂的c++代码行(嵌套的三元操作符)
- 三元操作符:抛出异常和嵌套
- 带有std::index_sequence的三元操作符
- 使用三元操作符从函数返回统一初始化
- 作为命令的三元操作符
- 使用带return的三元操作符
- 三元操作符的指针转换问题
- c++,三元操作符,std::cout
- 使用三元操作符时出现奇怪的错误
- 为什么三元操作符const我的字符串