PS/자주 하는 답변

sync_with_stdio(false) 이후에는 C와 C++의 입출력 방식을 섞어쓰면 안 됩니다.

djm03178 2023. 1. 26. 10:47

흔히 C++에서 입출력을 빨리 하는 기법이라고 해서 ios::sync_with_stdio(false); 라는 문장을 main 함수 상단에 넣곤 합니다. 그런데 이 문장이 왜 입출력을 빠르게 할까요? 그 답은 함수 이름에 직설적으로 들어있습니다. sync(hronize) with stdio, 말 그대로 stdio와 동기화를 한다는 뜻의 이름인데, 여기에 인자를 false를 주었으니, 동기화를 더 이상 안 하겠다는 의미입니다. 쉽게 말해서, ios (C++의 입출력 함수들)는 더 이상 stdio를 신경쓰지 않고 자기 갈 길을 가기 때문에 C++ 입출력 함수들의 속도가 향상될 수 있는 것입니다. 구체적으로는 이제 cin, cout 등이 자기 자신만의 입출력 버퍼를 두고 미리 입력받은 내용을 모아놓는다거나, 출력할 내용을 자기만의 버퍼에 모아두었다가 몰아서 출력하는 행위 등이 가능해집니다.

 

그렇기 때문에 이 함수를 사용할 때에는 반드시 지켜야 할 주의사항이 있습니다. 절대 sync_with_stdio(false)를 한 이후에는 두 입출력 방식이 섞여서는 안 됩니다. C의 입력 방식을 쓸 거라면 앞으로도 scanf, fgets, getchar 등의 입력 방식만 사용하고 cin, getline 등을 쓰면 안 되며, 반대도 마찬가지입니다. C의 출력 방식을 쓸 거라면 앞으로도 printf, puts, putchar 등의 출력 방식만 사용하고 cout 등을 쓰면 안 되며, 반대도 마찬가지입니다. 이 문장을 쓴 이후로는 C의 입력 함수로 입력받은 내역이 C++에 반영이 될지 안 될지 아무것도 보장이 되지 않고, 반대도 마찬가지입니다. printf로 출력한 내용과 cout으로 출력한 내용은 실제로는 어떤 순서로 섞여서 나타날지 모릅니다.

 

대표적인 실수 사례는 다음과 같습니다. 공백 없이 붙어서 주어지는 숫자들을 한 글자씩 입력받기 위해 다음과 같은 코드를 자주 작성하곤 합니다.

int a[55][55];

//////////////

ios::sync_with_stdio(false); // NO!!!!!!!!!

int n, m; // n은 행, m은 열
cin >> n >> m;

for (int i = 0; i < n; i++)
    for (int j = 0; j < m; j++)
        scanf("%1d", &a[i][j]);

이렇게 cin과 scanf를 섞어쓰려는 경우 절대 sync_with_stdio(false)를 해서는 안 됩니다. 이 문장을 남겨놓으려면 아예 n, m도 scanf로 입력받는다거나, 다른 방식으로 숫자들을 cin을 통해 입력받아야 합니다.