2017-05-09 11 views
1

code golf 경쟁 코드를 작성하는 동안 몇 가지 이상한 동작이 나타났습니다. 예를 들어 :C 컴파일러가이 오류를 잡아 내지 않는 이유는 무엇입니까?

int main(void) 
{ 
    goto jmp; 
    char *str = "Hello, World!"; 
jmp: 
    puts(str); 
} 

GCC (와 연타 및 MSVC) 어떤 경고 또는 오류의 결과로 컴파일하지만 실행은 SIGSEGV가 발생합니다. 컴파일러가 goto이 변수 선언을 뛰어 넘고 있다는 것을 어떻게 알지 못합니까? (? 버그)

나는 밖으로 이것을 테스트하기로 결정하고, 예를 재 작성 : 다시
int main(void) 
{ 
    goto jmp; 
    int x; 
jmp: 
    putchar(x); 
} 

는, 컴파일이 오류를 얻을 수 없습니다합니다. 또한 실행시 아무 것도 throw되지 않지만 MSVC에서는 프로세스가 0이 아닌 종료 코드로 종료됩니다.

여기 무슨 일 이니? 이것은 단순히 goto을 사용하지 않아야하는 또 다른 이유입니까? 그리고 두 번째 예제에서 오류가 발생하지 않는 이유는 무엇입니까? SIGSEGV은 처음에 throw됩니까?

+0

이것은 정의되지 않은 동작입니다. 변수 선언을 건너 뛰고 나중에 사용하려고합니다. 이것을하려고 시도하는 것조차도 어떻게 이해할 수 있습니까? 어떤 결과가 예상됩니까? – InternetAussie

+2

그건 컴파일러의 직업이 아니에요. – kaylum

+2

@InternetAussie OP는 그가 코드 골프라고 언급했습니다. 어쩌면 [this] (https://codegolf.stackexchange.com/q/23250/61563)에 도전 할 수 있을까요? –

답변

4

로컬 변수의 초기화를 건너 뛰는 것이 허용됩니다. 그 효과는 변수가 초기화되지 않은 것입니다.

초기화되지 않은 변수를 puts으로 전달하면 undefined behaviour이지만 제약 조건 위반이나 구문 오류는 발생하지 않습니다. 이것은 C 표준이 컴파일러에 오류를 요구하지 않는다는 것을 의미합니다.

그러나 컴파일러는 사려 깊고 다양한 경고 플래그를 제공하는 경향이 있습니다. 이 경우 gcc는 초기화되지 않은 변수의 잠재적 사용에 대해 경고 할 수 있습니다. -Wall 또는 -Wuninitialized을 사용하면 경고가 표시됩니다. -Werror 또는 -Werror=uninitialized을 사용하면 경고 대신 오류가 발생할 수 있습니다.

경고가있는 표준 모드에서 항상 컴파일하는 것이 좋습니다. -std=c11 -pedantic -Wall -Wextra.


"MSVC 관련하여 프로세스가 0이 아닌 종료 코드로 종료됩니다." , MSVC 컴파일러는 값을 반환하지 않고 main의 끝에서 떨어지는 C89 표준까지만 쓰레기를 반환합니다. 그런 고대 컴파일러를 지원해야한다면 이 main 끝에 있어야합니다.