Есть фрагмент кода, в котором GCC выдает результат, которого я не ожидал:
(Я использую gcc версии 4.6.1 Ubuntu/Linaro 4.6.1-9ubuntu3 для цели i686-linux-gnu)
[тест.с]
#include <stdio.h>
int *ptr;
int f(void)
{
(*ptr)++;
return 1;
}
int main()
{
int a = 1, b = 2;
ptr = &b;
a = b++ + f() + f() ? b : a;
printf ("b = %d\n", b);
return a;
}
В моем понимании, есть точка следования при вызове функции. Пост-инкремент должен выполняться перед f().
см. C99 5.1.2.3: «... называемые точки последовательности, все побочные эффекты предыдущих оценок должны быть завершены, и никаких побочных эффектов последующих оценок не должно быть».
Для этого тестового случая, возможно, порядок оценки не указан, но окончательный результат должен быть таким же. Поэтому я ожидаю, что окончательный результат b будет равен 5. Однако после компиляции этого случая с помощью «gcc test.c -std=c99» вывод показывает b = 3.
Затем я использую "gcc test.c -std=c99 -S", чтобы посмотреть, что произошло:
movl $1, 28(%esp)
movl $2, 24(%esp)
leal 24(%esp), %eax
movl %eax, ptr
movl 24(%esp), %ebx
call f
leal (%ebx,%eax), %esi
call f
addl %esi, %eax
testl %eax, %eax
setne %al
leal 1(%ebx), %edx
movl %edx, 24(%esp)
testb %al, %al
je .L3
movl 24(%esp), %eax
jmp .L4
.L3:
movl 28(%esp), %eax
.L4:
movl %eax, 28(%esp)
Кажется, что GCC использует оценочное значение перед f() и выполняет операцию «++» после двух вызовов f().
Я также использую llvm-clang для компиляции этого случая, и результат показывает b = 5, чего я и ожидаю.
Правильно ли я понимаю поведение постинкремента и точки следования?? Или это известная проблема GCC461??