Для награды: Как можно отключить это поведение в каждом конкретном случае, не отключая или не понижая уровень оптимизации?
Следующее условное выражение было скомпилировано на MinGW GCC 3.4.5, где a
имеет тип signed long
, а m
имеет тип unsigned long
.
if (!a && m > 0x002 && m < 0x111)
В качестве CFLAGS
использовались -g -O2
. Вот соответствующий вывод GCC сборки (выгруженный с помощью objdump
).
120: 8b 5d d0 mov ebx,DWORD PTR [ebp-0x30]
123: 85 db test ebx,ebx
125: 0f 94 c0 sete al
128: 31 d2 xor edx,edx
12a: 83 7d d4 02 cmp DWORD PTR [ebp-0x2c],0x2
12e: 0f 97 c2 seta dl
131: 85 c2 test edx,eax
133: 0f 84 1e 01 00 00 je 257 <_MyFunction+0x227>
139: 81 7d d4 10 01 00 00 cmp DWORD PTR [ebp-0x2c],0x110
140: 0f 87 11 01 00 00 ja 257 <_MyFunction+0x227>
120
- 131
можно легко отследить как первое вычисление ! A
, затем по оценке m> 0x002
. Условное условие первого перехода не происходит до 133
. К этому времени два выражения были вычислены, независимо от результата первого выражения: ! A
. Если a
было равно нулю, выражение может (и должно) быть завершено немедленно, чего здесь не делается.
Как это соотносится со стандартом C, который требует, чтобы логические операторы выполняли короткое замыкание, как только можно определить результат?