C++ 三值运算符作为命令?

C++ 三值运算符作为命令?,c++,c,ternary-operator,deobfuscation,C++,C,Ternary Operator,Deobfuscation,在中,为了减小代码的大小,通常使用三元运算符: /* 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; 这条线的作用并不明显。乍一看,它似乎是在为两个数组元素之一赋值,但事实并非如此。更确切地说,它似乎是在对数组元素进行o

在中,为了减小代码的大小,通常使用三元运算符:

/* 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;
这条线的作用并不明显。乍一看,它似乎是在为两个数组元素之一赋值,但事实并非如此。更确切地说,它似乎是在对数组元素进行or运算,或者什么都不做(运行“command”
1

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

字面上的等价物是:

if (q[11])
  q[3]|=4;
else
  1;
三元运算符通常用作表达式的一部分,因此将其视为独立命令似乎有些奇怪。再加上看似不合适的
1
,这行代码几乎可以称为模糊代码

我做了一个快速测试,能够编译并运行一个C(++)程序,其中数据常量为“command”,例如
void main(){0;'a';“foobar”;false;}
。是的,但我找不到任何关于这种用法的信息-)


可以解释一下它是什么和它是如何工作的吗?

< P>在C和C++中,任何表达式都可以通过放<代码>来表述;代码>在末尾

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


试图“禁止”某些表达式子集具有
,这将使语言变得不必要的复杂化跟在他们后面。这个代码不是很有用,但它是合法的

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

“在微型C程序中,定义重用的表达式是常见的做法 使代码更小“

是完全b***s***。这句话正是事情开始严重出错的地方

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

除非你是在80年代中期的8086计算机上编程,硬盘空间非常有限,否则你永远不需要“减少代码的大小”。而是编写可读的代码

也就是说,由于
q
是一个字符数组,因此您链接的代码相当于

if(q[11])
{
  (int)(q[3] |= 4);
}
else
{
  1;
}
如果
1
是一条没有副作用的语句,它将得到优化。之所以放在那里,是因为
?:
操作员需要第三个操作员

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

为了增加可读性并生成自文档代码,代码应该重写为

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


作为旁注,这里有一个bug:
q[2]|=128
q
是char类型,它具有实现定义的符号性,因此这一行可能是灾难性的。核心问题是,千万不要将
char
类型用于逐位运算或任何形式的算术,这是一个典型的初学者错误。它必须替换为
uint8\t
无符号字符

q[11]
,而不是
q[1]
。你的分析是正确的;如果没有更大的上下文,它相当于
if(q[11]){q[3]|=4;}
,只是更短“这行代码几乎可以说是模糊代码”-事实上“有人能准确地解释它是什么以及它是如何工作的吗?”-你的问题正确地描述了这两个方面。这是糟糕的代码。使用
q[11]&&(q[3]|=4)不仅仅是复杂-一堆函数几乎无法使用,比如
printf
-你能想象写
int outputted=printf(“…”)每次?:)<代码>在C和C++中,任何表达式都可以通过语句来表述;最后。
当然,POD类型(“内置”)都是表达式……这很有意义。当然,它们不一定意味着什么,对吗?我想你需要知道这些混淆代码的细节。我本以为需要专门编写对象来支持作为表达式使用,但显然不是这样;那是内置的。我刚刚用
myclass进行了测试。这几乎让我想起了Python和Ruby等高级语言,它们的代码类似于
1.to_s
。特别具有讽刺意味的是,如果代码的作者如此担心源代码的大小,以至于他们选择使用模糊的语句形式来保存一个字节,然后,他们使用?b:c表单添加
,在注释中保存一个字节
——这33个字节可能会删除任何由模糊代码保存的内容@TripeHound,即代码的扩展解释版本。没有包含任何注释(除了在开始解释许可证时的可选注释)。@Lundin,该特定代码仅用于作为最小DNS服务器。他们的目标是达到目标,就像高尔夫一样。但是很好地抓住了这个bug,谢谢你的解释。@Synetech仍然没有解释为什么他们会减少源代码本身。实际上,编写代码的人似乎并不理解源代码大小和二进制可执行文件大小之间的区别。
if (q[AR_INDEX] != 0)
{
  q[REPLY_INDEX] |= NOT_IMPLEMENTED;
}