2017-04-03 3 views
0

빠른 간단한 질문; 는이C : 다른 크기의 구조로 캐스팅

typedef struct {int a; int b;} S1; 
typedef struct {int a;} S2; 
((S2*)(POINTER_TO_AN_S1))->a=1; 

항상 구조의 멤버를 반환 (및 지정)합니까? 아니면 정의되지 않은 동작입니까?

+0

언어 태그는 코드가 관련되어있을 때 중요합니다 (즉, 스택 오버플로에서 거의 항상 여기에 있음). – crashmstr

답변

0

준수 컴파일러에서 구조체가 액세스되는 곳에서 볼 수있는 공용체 형식의 완전한 정의 내에 두 구조체 형식이 모두 나타나고 포인터의 대상이 해당 공용체 형식의 인스턴스가 된 경우 정의되어야한다. 표준에서는 컴파일러가 포인터의 대상이 실제로 해당 공용 형식의 개체인지 알 수있는 방법이 필요하지 않습니다. 단순히 전체 공용 형식 선언이 표시 될 수 있습니다.

그러나 -fno-strict-aliasing 플래그가 사용되지 않는 한 gcc는 여기의 표준을 준수하지 않습니다. 전체 공용 구조체 유형이 표시되고 컴파일러가 실제로 공용 구조체의 객체로 작업하는 것을 볼 수있는 경우에도 gcc는 별칭을 무시합니다. 예를 들어, 주어진 :

struct s1 {int x;}; 
struct s2 {int x;}; 
union u { struct s1 s1; struct s2 s2;}; 

int read_s1_x(struct s1 *p) { return p->x; } 
int read_s2_x(struct s2 *p) { return p->x; } 
int write_s1_x(struct s1 *p, int value) { p->x = value; } 
int write_s2_x(struct s2 *p, int value) { p->x = value; } 

int test(union u *u1, union u *u2) 
{ 
    write_s2_x(&u2->s2, 0); 
    if (!read_s1_x(&u1->s1)) 
    write_s2_x(&u2->s2, 1); 
    return read_s1_x(&u1->s1); 
} 

컴파일러가 더 U1-> s1.x는 기록 후 U2-> s2.x, 비록의 값을 다시 읽어 필요가 없다고 결정하는 것 완전한 조합 유형 이 표시되며 컴파일러에서 u1과 u2가 모두 유니온 유형의 객체에 대한 포인터임을 알 수 있습니다. 나는 gcc의 저자가 이 결과 포인터가 심지어 해당 멤버 유형의 객체에 액세스하는 데 사용될 수없는 경우에도 공용체 유형에 적용될 때 address-of 연산자가 의미한다고 생각하는지 확실하지 않습니다.