C中的高级IF语句

时间:2009-08-18 10:27:45

标签: c if-statement

我只是使用IDA反向设计二进制文件并加载Hex Ray以检查特定功能。 generate C源代码包含以下if语句:

LP_ret_GlobalLock_1 = GlobalLock(hMem);
LP_ret_GlobalLock_2 = LP_ret_GlobalLock_1;
...
if ( !LP_ret_GlobalLock_1 || (v9 = *(_DWORD *)(v6 + 4), *(_DWORD *)v6 = LP_ret_GlobalLock_2, v9 < 0) )

我不确定完全理解以下部分:

(v9 = *(_DWORD *)(v6 + 4), *(_DWORD *)v6 = LP_ret_GlobalLock_2, v9 < 0)

v9初始化为v6 + 4;但是后来v6被修改为指针LP_ret_GlobalLock_2,最后v9检查是否小于0.这是正确的吗?在计算v9时,v6使用了什么值? LP_ret_GlobalLock_2或之前的值?

6 个答案:

答案 0 :(得分:5)

我猜你问的是comma operator。它在逗号之前计算表达式,然后在逗号之后计算表达式,整个事物的结果是第二个表达式的结果。

首先是v9 = *(_DWORD *)(v6 + 4),然后是*(_DWORD *)v6 = LP_ret_GlobalLock_2,然后是v9 < 0。在评估了前两个表达式之后,结果是v9 < 0的结果。

我知道你是通过逆向工程得到的。我永远不会在if语句中使用带有副作用的逗号运算符,就像我自己编写代码一样;它太混淆了。

答案 1 :(得分:3)

就我所见,变量v6是一个指针。另外,我假设_DWORD是32位数量。这是细分:

  • v9 = *(_DWORD *)(v6 + 4)v9被分配给v6指向的32位字后面的32位字。
  • *(_DWORD *)v6 = LP_ret_GlobalLock_2v6指向的32位字被赋予LP_ret_GlobalLock_2的值。
  • v9 < 0:表达式求值为v9 < 0,即如果v6指向的32位字后面的32位位字小于零,则为真。

如果_DWORD是无符号值v9,则永远不会为负值且表达式始终为false。

答案 2 :(得分:2)

如果在C中编译,则表达式从左到右进行计算。因此,在计算v9时,使用v6的初始值。

最终,v9被检查为0,所以你是对的。

简单地说,执行相当于:

v9 = *(_DWORD *)(v6 + 4);
*(_DWORD *)v6 = LP_ret_GlobalLock_2;
return v9 < 0;

但是,我不建议使用您提供的那种复杂的代码,这些代码很难阅读和理解,并且在维护时可能容易出错。将报表扩展为独立报表要好得多。

答案 3 :(得分:2)

理解这句话的作用的关键是逗号运算符。逗号运算符的优先级低于所有其他运算符。它从左到右计算所有子表达式,然后返回最后一个的子表达式。所以,例如,

int a, b;
b = (a=1, a+1);

会将b设置为2。

所以回答你的问题:

  

v9初始化为v6 + 4;但是v6被修改为指针LP_ret_GlobalLock_2,最后v9检查是否小于0.这是正确的吗?

  

在计算v9 v6使用的值时? LP_ret_GlobalLock_2或之前的值?

之前的值。

答案 4 :(得分:2)

部分

if (v9 = *(_DWORD *)(v6 + 4), *(_DWORD *)v6 = LP_ret_GlobalLock_2, v9 < 0)

的评估就像

一样
v9 = *(_DWORD *)(v6 + 4);
*(_DWORD *)v6 = LP_ret_GlobalLock_2;
if (v9 < 0)
/* ... */

任何逗号分隔表达式从左到右计算,表达式的结果是右边部分的结果。与if子句相关的是(v9&lt; 0),在修改v6之前,在第一部分中分配了v9。

答案 5 :(得分:1)

C中的逗号运算符是序列运算符。所以,你的假设是正确的。

但请注意,第二项作业不会改变v6。它改变了v6 [0],即v6指向的值。 v9的分配从v6 [4]读取。