2012-08-15 5 views
3

의 시퀀스 포인트 개념은 GCC는 결과를 코드 조각은 내가 기대하지 않았다가 목표는 i686-리눅스 GNU위한 -9ubuntu3) 내 이해후 증가, 함수 호출, GCC

[TEST.C]

#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는 "무슨 일이 있었는지 볼 수 있습니다 : GCC는 F 전에 평가 값()를 사용하고 실시 할 것을 보인다

 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) 

'++' 작업이 F 후()를 호출합니다.

또한이 경우를 컴파일하려면 llvm-clang을 사용하고 결과는 b = 5로 표시됩니다. 이는 예상 한 것입니다.

포스트 증가 및 시퀀스 포인트 동작에 대한 나의 이해가 올바르지 않습니까 ?? 또는 이것은 GCC461의 알려진 문제입니까?

+0

Welcome to StackOverflow! 연구를 위해 복사 - 붙여 넣기를 원하는 프로그램 라인에 번호를 매기 지 마십시오. –

+0

오 ~ 확인! 이제 프로그램 줄 수를 제거했습니다. 상기시켜 주셔서 감사합니다! :) –

답변

3

나는이 GCC 버그를 언젠가보고했으며, 금년 초에 수정되었다. http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48814

+0

고마워요! GCC 4.6.1의 버그 인 것 같습니다. 최신 GCC 버전을 체크 아웃하고 빌드 한 다음이 샘플을 다시 시험해 보겠습니다. 정말 고맙습니다! :) –

4

Clang 외에도 참조 용으로 사용할 수있는 두 가지 도구가 있습니다 (Frama-C's value analysisKCC). 컴파일러와 달리 C 프로그램의 정의를 검사하는 데 사용할 수 있습니다. 대상 프로그램이 정의되지 않은 것으로 표시되는지 여부를 알려주기 위해 설계되었습니다. 행동.

그들은 그들의 거친 가장자리를 가지고 있지만 모두 b 확실히 프로그램의 마지막에 정의되지 않은 동작으로 5해야한다고 생각 :

Mini:~/c-semantics $ dist/kcc ~/t.c 
Mini:~/c-semantics $ ./a.out 
b = 5 

이 그렇게 생각 연타보다 더 강한 인수 (이후입니다 정의되지 않은 동작 인 경우 Clang은 여전히 ​​b = 5을 인쇄하는 프로그램을 생성 할 수 있습니다.

GCC 버전에서 버그를 발견 한 것 같습니다. 다음 단계는 SVN이 여전히 존재하는지 확인하기 위해 SVN을 체크 아웃하는 것입니다.

+0

고마워요! 그것들은 프로그램을 검증하는 매우 유용한 도구입니다!그런데 요하네스 샤 우브 (Johannes Schaub)는이 버그를보고했으며 올해는 고정되어 있다고 말했다. 나는 최신 GCC 버전을 체크 아웃하고 다시 시도 할 것이다. :) –