Type Qualifiers of C99

역할을 제한하기 위한 용도로 사용

Posted 2022-03-01 17:00:00 ‐ 2 min read

오늘 42Seoul 본과정의 가장 첫 프로젝트인 libft를 등록했다.

만들어야 할 함수들의 프로토타입을 확인하다가, 참고사항에

특정 함수의 프로토타입에는 restrict 한정자를 사용하세요.

라고 의외로 친절한(?) 팁이 적혀있었는데, 저 키워드가 어떤 역할을 하는지 전혀 알지 못했다.

그래서 찾아 보았다.

한정자(Type qualifiers)1

영어로는 자격을 주는 것 같은데, 한글로는 뭔가를 제한하는 느낌이다.

왜 이런 이름이 지어졌을까? 한정자의 역할 때문이다.

먼저, 한정자는 뭔가를 제한하기 위해서 사용한다.

뭘? 익숙한 const 한정자부터 보면

  1. const: 데이터의 변경권을 제한한다.
  2. volatile: 컴파일러의 최적화를 제한한다.
  3. restrict: 데이터에 접근 할 수있는 변수를 제한한다.

restrict2

restrict 키워드가 있다면 a, b, x가 모두 다르다는 것을 명시하는 것이다. (하지만 세 변수가 같은 곳을 가리킨다고 컴파일 오류가 나지 않기 때문에 사람이 일일이 확인해줘야 한다.) 포인터가 가리키는 곳이 모두 다르다면 아래와 같은 함수에서 각 명령의 순서는 바뀌어도 상관없다. 과연 빌드했을 때 프로그램은 우리가 의도한 대로 동작할까?

void increase(int *restrict a, int *restrict b, int *restrict x)
{
    *a += *x;
    *b *= *x;
}
int v = 5;
increase(&v, &v, &v);
$ gcc -std=c99 -O3 -c increase.c
$ ./increase
50

놀랍다. 5 + 5 = 10 하고 난 뒤 10 * 10 = 100 이어야 하는데 결과는 50 이다. 아무래도 컴파일러 최적화로 인해서 5 * 5 = 25, 25 + 25 = 50 로 순서가 바뀐 것 같다.

그렇다면 restrict 키워드를 제거하고 빌드 하면 어떻게 될까?

void increase(int * a, int * b, int * x)
{
    *a += *x;
    *b *= *x;
}
int v = 5;
increase(&v, &v, &v);
$ gcc -std=c99 -O3 -c increase.c
$ ./increase
100

우리가 의도한 대로 결과가 나왔다.

restrict 키워드를 사용할 때 정말 해당 키워드의 데이터 접근 권한이 제한되었는지 확인할 필요가 있을 것 같다. 이를 하지 않는다면 위와 같은 오류가 생길 수도 있으니 사용에 주의하자.

참고문헌