처음에 21번째줄에 flag를 초기화시키지 않아서 계속 틀렸습니다.

그런데 대부분의 컴파일러는 변수를 초기화시키지 않으면 garbage 값을 갖는 것으로 알고 있습니다.

그래서 원래 "NO"를 출력할 경우가 아닐 때 높은 확률로 flag는 1이 아닐 것이고 아래 코드도 통과될 것이라고 생각했습니다.

그러나 여러번 시도해보아도 틀렸습니다를 받았습니다.

혹시나 컴파일러가 초기화되지 않는 값을 특정 값으로 변경하나 싶어서 1이 아닌 임의의 값으로 변경해서 테스트를 해봐도

여전히 틀렸습니다를 받았습니다.

백준 사이트가 초기화되지 않는 변수를 사용하는 경우 무조건 틀렸습니다로 처리하는 걸까요? 

djm03178   3년 전

채점 프로그램은 그저 출력한 값이 정답과 일치하는지를 확인할 뿐이므로 초기화를 안 했다는 것 자체로 어떤 판정을 내리지는 않습니다. 그런 부분이 있는지에 대한 체크 자체를 일절 하지 않습니다. 초기화가 문제든, 다른 것이 문제든 결과적으로 틀린 답이 출력되었을 때에만 틀렸다고 판정합니다.

위 코드 21번째 줄을 주석처리를 해보고 실행을 했을 때

NO가 나와야할 경우에 NO가 나오는 경우(55번째줄)는 항상 정상입니다. 

NO가 나와야할 경우에 60번째 줄, 정답출력으로 가는 경우는 없습니다.

따라서 틀렸습니다를 받은 경우는 정답 출력이 나와야하는 경우에 NO가 나와서 틀린 경우밖에 없습니다.

그런데 정답출력이 나와야하는 경우에 flag가 아주 드문 확률로 1이라는 값을 가질텐데,

그런데 여러 번 테스트를 해봐도 이런게 정상적인 확률로는 보이지 않아서 드렸던 질문입니다.

djm03178   3년 전

쓰레기값이라는 것은 컴퓨터가 임의로 난수를 생성하는 것이 아니기 때문에 특정 값에 더 몰릴 가능성이 큽니다. 특히 메모리 상에 가장 흔한 값은 0이고, 그 다음은 아마도 1일 것이라고 생각합니다. 1이 나올 확률이 낮지 않습니다.

게다가 채점 프로그램이 프로그램을 여러 번 실행할 때 같은 공간을 반복해서 쓰는 경우 이전에 실행했을 때 남아있던 값이 똑같은 자리에 그대로 배정될 수도 있습니다. 그래서 이전 케이스에서 flag에 1을 담은 적이 있었다면 다음 번 실행할 때 이 자리에 그대로 1이 남아있을 수도 있습니다. BOJ가 채점에 스레드를 사용하는 것으로 알고 있어서, 이렇게 될 가능성이 아주 높다고 생각합니다.

좀 더 원론적인 이야기로 들어가자면 초기화되지 않은 변수를 사용하는 것 자체가 undefined behavior이기 때문에 컴파일러가 흑마법을 부렸을 가능성도 없지 않습니다. 초기화되지 않았다는 것이 원칙적으로 어떤 유효한 값을 가지고 있어야 한다는 뜻은 아니기 때문입니다. 초기화되지 않은 경우 조건문이 그냥 만족된 것으로 처리되게끔 기계어가 만들어졌을 수도 있습니다.

seico75   3년 전

백준 사이트에서 고의로 날리는 것은 아니고 컴파일러단에서 일어나는 일입니다.

백준 사이트에서는 C++를 빌드할때 -O2 옵션으로 최적화를 수행합니다.  이 과정에서 필요없는 코드는 과감히 삭제를 하기도 하는데,

이 과정에서 flag != 1인 경우가 없어지는 것 같습니다.

컴파일러 입장에서는 코드상에 flag 가 1로 셋팅되는 경우 외에는 다른 경우가 안보이니까 flag 는 항상 1 인가보다 하고 나머지 코드를 날려 버리는 것 같네요.

g++ src.cpp 

으로 빌드하면 값이 나오고 (정확히는 쓰레기 값으로 인하여 flag == 1 인 경우가 확률상 적으니 나오는 경우도 있고...)

21 라인에 flag = 0; 대신에 if (n == 200000) flag = 0; 을 하고 

g++ -O2 src.cpp

값이 (많은 경우) 나오네요. (실제 제출해도 정답처리.)

이것은 컴파일러 입장에서는 n == 200000 이 나오지 않는다는 사실을 모르니 

flag == 1 이 아닌 경우도 있다고 하고 최적화를 적당한 수준으로 할것이고.. 생각하신 방식대로 동작해서 쓰레기값인 경우 답이 출력되게 되는 것 같습니다.

아무튼.. 

앞에 분이 말씀하신 것과 같이 정의되지 않은 동작이므로 어떤 결과나 나와도 이상하지 않는 것입니다.

그리고..

int main(void) 에는 return 값이 있어야 합니다.  너무 많은 분들이 안쓰시네요.

djm03178   3년 전

C++ 표준상에서 main만은 예외로 리턴값이 없어도 0을 리턴해줍니다.

확인해본 결과 컴파일러가 임의로 해당 부분을 제거하고 실행하는 것을 확인했습니다.

-O2 플래그만 추가하고 돌려도 잘못된 결과가 나오네요.

마지막 조건문의 else절은 아예 무시해버리고 if 내부만 실행하는 것으로 보입니다.

답변해주신 두 분 모두 감사드립니다.

댓글을 작성하려면 로그인해야 합니다.