2011-08-15 6 views
13

다음 코드는 별칭 위반 등의 이유로 정의되지 않은 동작을 호출합니까? ab 동일한 유형에 대한 포인터 수 있으므로 별명 서로 허용 때문에 일반 int *보다는 포인터 - 어레이 유형을 사용하여 해당 코드가 완벽하게 합법적 될 것이라고배열 포인터 앨리어싱 - 정의되지 않은 동작?

int foo(int (*a)[10], int (*b)[5]) 
{ 
    (*a)[5]++; 
    return (*b)[0]; 
} 

int x[10]; 
foo(&x, (int (*)[5])&x[5]); 

참고.

편집 :이 사실 앨리어싱 위반 인 경우 흥미로운 결과는, restrict 의미 사전 C99을 얻을 수있는 hackish하지만 유효한 방법이 될 것으로 보인다는 것이다. 마찬가지로 : 각 주소에 실제 배열에 액세스하는 데 필요한 아마도 경우

void some_func(int *aa, int *bb) 
{ 
    int (*a)[1] = (void *)aa; 
    int (*b)[2] = (void *)bb; 
    /* Now **a and **b can be assumed by the compiler not to alias */ 
} 

, 당신은 서로 다른 크기로 SIZE_MAX-1과 SIZE_MAX-2 등을 사용할 수 있습니다.

+1

이들은 동일한 유형의 포인터이며 별칭이 아닌 것으로 간주 될 수 없습니다. –

답변

4

는 현재 다른 유형의 포인터를 통해 개체에 액세스되지 않은 : 당신은 배열 오브젝트를 조작하지 않습니다에있는 a 스스로하지만 객체가 (*a)+5(*b)+0, 즉 *((*a)+5)*((*b)+0) 가리키는 b 점. 이들은 동일한 유형의 포인터이기 때문에 동일한 객체에 별칭을 지정할 수 있습니다. (x 외에 한번만 평가되는) 단순 할당 = 대한 표준

말한다 x = x + 1++ 등가이다

++ 오퍼레이터 암시 과제는 객체에 대한 유효한 할당 (*b)+0이 가리키는 객체에 저장된 값이 다른 객체에서 읽혀지는 경우 은 어떤 방식 으로든 첫 번째 객체의 저장과 겹치기 때문에 중첩이 정확해야하며 두 객체는 ​​정규화 된 호환 가능 유형의 정규화 된 버전을 가지게됩니다 (). 예프. 그렇지 않은 경우 동작은 입니다.

여기의 유형은 정확히 동일하며 겹치기가 정확합니다.

+0

+1 매우 흥미 롭습니다. 하지만, 나는 여전히이 모든 포인터 의미 정보를 싫어한다 ... –

+0

이 논리에 따르면, int [5] [5]와 overlay 된 int [25]에 접근하지 않는 것이 유효 할 것이다 ...? –

+0

@R .. 네, 그렇습니다. 배열은 어떻게 든 회색 영역에 있습니다. 'struct'에 대해서'toto.x'라는 필드에 접근하는 것은 객체 전체에 접근하는 것이 분명합니다.'A [24]'와'B [4] [4]'는 포인터 산술에 의해 정의되므로 절대 접근하지 않습니다. 배열 전체. –