컴파일러
위의 함수에서 컴파일러가 *b의 읽기를 루프 밖으로 내보내는 최적화를 그대로는 수행할 수 없는 이유는?
void add(int *a, int *b, int n) {
for (int i = 0; i < n; i++)
a[i] += *b;
}
- A*b는 정수이므로 루프 밖으로 내보내면 값의 정밀도가 떨어지기 때문에
- Ba와 b가 같은 장소를 가리킬 가능성이 있어 a[i]에 대한 쓰기로 *b가 바뀔 수 있기 때문에
- C포인터를 인수로 받는 함수는 컴파일러가 일절 최적화해서는 안 된다는 규칙이 있기 때문에
정답과 해설 보기
정답: B. a와 b가 같은 장소를 가리킬 가능성이 있어 a[i]에 대한 쓰기로 *b가 바뀔 수 있기 때문에
얼핏 보면 *b는 루프 안에서 바뀌지 않으므로 1번만 읽으면 될 것 같습니다. 그러나 호출하는 쪽이 add(x, &x[3], n)처럼 b가 a의 요소를 가리키는 포인터를 전달하면, a[3]에 대한 쓰기로 *b의 값이 바뀝니다. 컴파일러는 이 가능성(에일리어스)을 부정할 수 없으므로 매번 다시 읽는 코드를 생성합니다. C 언어에서는 포인터에 restrict를 붙여 다른 장소를 가리킨다고 약속하면 최적화할 수 있습니다. 정밀도의 문제도, 최적화가 금지되어 있는 것도 아닙니다.
- A. 정수 읽기를 옮겨도 정밀도는 변하지 않습니다.
- B. 올바릅니다. a와 b가 겹칠 가능성(에일리어스)이 있기 때문입니다.
- C. 포인터를 사용하는 함수도 최적화됩니다.