2017-11-22 2 views
1

에 다음 예제를 보았습니다.제한 한정자의 정의되지 않은 동작에 대한 혼동

void f(int n, int * restrict p, int * restrict q) 
{ 
    while(n-- > 0) 
     *p++ = *q++; // none of the objects modified through *p is the same 
        // as any of the objects read through *q 
        // compiler free to optimize, vectorize, page map, etc. 
} 
void g(void) 
{ 
    extern int d[100]; 
    f(50, d + 50, d); // OK 
    f(50, d + 1, d); // Undefined behavior: d[1] is accessed through both p and q in f 
} 

이 예에서는 f(50, d + 50, d);을 호출하는 것이 좋습니다.

하지만 이해가 안되는 전화는 f(50, d + 1, d)입니다. 정의되지 않은 동작입니다. 왜?

+2

함수'f'의 객체'd [1]'은'p'와'q'를 통해 접근하기 때문에. 의견은 그것을 말하고있다. –

+0

'포인터의 수명'이 두 포인터에 영향을주는 함수 호출이기 때문에 여기서는 제한적이라고 생각하지 않습니다. 정의되지 않은 일반적인 동작은 함수'f'에서 @MartinBeckett –

+0

에 적용됩니다. 두 포인터가 모두 제한되어 있지만 다른 시점에 같은 객체를 가리키고 있습니다. –

답변

4

포인터의 restrict 한정자는 해당 포인터를 통해 액세스되는 모든 객체가 해당 포인터의 수명 동안 다른 포인터를 통해 액세스되지 않는다는 것을 의미합니다. 즉, 객체가 p 포인터를 통해 액세스되고 p의 범위 동안 수정 된 경우 해당 범위의 p을 통해서만 액세스 할 수 있습니다. 이 제약 조건을 위반하면 정의되지 않은 동작이 발생합니다. f(50, d + 50, d);에서

, pd[99]까지 d[50]을 수정하는 데 사용되며, qd[49]까지 d[0]에 액세스하는 데 사용됩니다. 겹침이 없으므로 모든 것이 잘됩니다. f(50, d + 1, d);에서

, pd[50]까지 d[1]을 수정하는 데 사용되며, qd[49]까지 d[0]에 액세스하는 데 사용됩니다. 일부 요소 (예 : d[1])는 p을 통해 수정되고 q을 통해 읽으므로 restrict 한정자를 위반 한 것입니다.

관련 문제