C의 구조 확장
다음과 같이 정의 된 2 개의 구조가 있다고 가정합니다.
typedef struct {
T x;
T y;
} A;
typedef struct {
A a;
T z;
} B;
구조 B에 대한 포인터를 구조 A에 대한 포인터로 취급 할 수 있습니까?
실제로 다음은 신뢰할 수있는 / 표준 / 이식 / 컴파일러 불변입니다.
B b = {{1,2},3};
A * a = &b;
print(a->x);
print(a->y);
답변
C17 6.7.2.1은 다음과 같이 설명합니다 (강조 내) :
구조 객체 내에서 비트 필드가 아닌 멤버와 비트 필드가있는 단위에는 선언 된 순서대로 증가하는 주소가 있습니다. 적절하게 변환 된 구조체 객체에 대한 포인터는 초기 멤버 (또는 해당 멤버가 비트 필드 인 경우 해당 멤버가 상주하는 단위)를 가리키고 그 반대의 경우도 마찬가지 입니다.
즉, B b
개체에 대한 포인터를 첫 번째 멤버의 형식으로 "적절하게 변환"해야합니다 . 이 변환은 암시 적으로 발생하지 않으며 명시 적 캐스트를 통해 수행해야합니다.
A * a = (A*)&b;
그렇게하는 것은 위에 인용 된 부분에 따라 잘 정의되고 안전합니다.
마찬가지로 컴파일러는에 대한 포인터 A
와에 대한 포인터가 B
별칭 을 사용 하지 않는다고 가정 할 수 없습니다. 유효 유형 6.5.7 ( "엄격한 별칭 지정") 규칙은이 경우에 예외를 제공합니다.
객체는 다음 유형 중 하나를 가진 lvalue 표현식에 의해서만 액세스되는 저장된 값을 가져야합니다.
...
- 멤버 중 앞서 언급 한 유형 중 하나를 포함하는 집계 또는 공용체 유형
예를 들어, 최적화 중에 함수를 호출하는 컴파일러 void func (B* b)
는 extern A a;
다른 번역 단위에 정의 된 외부 계보 변수 가 함수에 의해 변경되지 않았다고 가정 할 수 없습니다.