2012-11-14 5 views
8

나는 아래 그림과 유사한 데모로 구현 한 코드 .. structs/unionsC에서 이름없는 struct/union의 이점은 무엇입니까? <code>ISO C11</code> 허용하는

struct st 
{ 
int a; 
struct 
{ 
int b; 
}; 
}; 

6.58 이름 struct/union 필드를 발견했다.

하지만 이점은 무엇입니까?

어쨌든 내가 함께 GCC 4.5.2에서 컴파일

int main() 
{ 
struct st s; 
s.a=11; 
s.b=22; 
return 0; 
} 

같은 동일한 방식으로 데이터 멤버에 액세스 할 수 있기 때문에,

gcc -Wall demo.c -o demo 

및 오류없이,

+0

가능한 복제본 [C11에서 유용한 익명의 구조체 및 공용체는 무엇입니까?] (http://stackoverflow.com/questions/8932707/what-are-anonymous-structs-and-unions-useful-for-in- c11) –

답변

14

구조체 내부에 익명 구조체가있을 필요는 없습니다.이 구조체는별로 유용하지 않습니다. 일반적으로 더 많은 패딩을 도입하여 레이아웃을 약간만 변경하고 다른 보이는 효과는 없습니다 (멤버를 인라인하는 것에 비해). 자식 구조체를 부모 구조체로 변환).

익명 구조체/공용체의 장점은 다른 곳에서 생각합니다 : 익명 구조체를 구조체 내부의 공용체 또는 익명 공용체 내부에 배치하는 데 사용할 수 있습니다.

예 :

union u 
{ 
    int i; 
    struct { char b1; char b2; char b3; char b4; }; 
}; 
+1

이 공용체를 사용하는 방법을 설명 할 수 있습니까? 예를 들어 인스턴스 x가 u이고'x.b1 = 'a' '를 사용하면 나머지 b2, b3, b4가 초기화되고 메모리 공간을 차지합니까? – Herbert

+0

@Herbert 노조 내부의 전통적인 (명명 된) 구조체와 동일합니다. 귀하의 질문은 구조체를 포함하는 노동 조합에 관한 것입니다. 더 구체적인 질문에 대한 답변에 대한 주석 대신에 SO 질문으로해야하지만, 후자를했기 때문에 'x.b1 ='a ''는 b2, b3 멤버를 초기화하지 않습니다. ,'b4' 그러나 이것은'sizeof (union u)'의 값을 출력하여 볼 수 있듯이 "메모리 공간을 차지합니다". 이론적으로,'b1' 멤버 만 사용하는'union u' 변수를 선언하면 충분히 스마트 한 컴파일러는'b1'을위한 메모리를 예약 할 수 있습니다 ... –

+0

@Herbert하지만 원칙적으로'union u'를 선언합니다 object는 나중에 포함 된 struct의 멤버 중 하나에 쓸 수 있기 때문에 메모리를 예약해야합니다. –

11

장점은 꽤 명백한가요? 그것은 프로그래머가 이름을 얻지 못하게합니다! naming things is hard부터 실제 필요가 없다면 그렇게하지 않는 것이 좋습니다.

struct가 로컬 결코 다른 곳에서도 사용하지만, 정말 좋은 정보가 정말 부모 구조체의 필드가되는 상황에서 불필요한 커플 링의 가능성을 감소시키기 때문에 것이 또한 매우 분명한 신호입니다 .

생각해 보면 static; static이 전역 심볼의 가시성을 표시하는 컴파일 단위로 제한하는 것과 유사한 방식으로 (물론 동일하지는 않지만) 내부의 가시성을 외부의 것으로 제한합니다.

+0

조금 정교합니다 .. 정적 ?? 그 중 하나가 지역 내부에 있으면 식별자의 같은 이름을 사용하면 오류가 발생합니다 ..하지만 함수에서 우리는 블록 범위 때문에 {} 안에 같은 이름의 식별자를 부여 할 수 있습니다 왜 여기에 허용되지 않습니다 struct {} – Omkant

+4

'struct' 프로그래머가 부모 구조체에 멤버를 직접 인라인하지 않는 이유를 이해하기 어렵도록 로컬이됩니다. 현재 버전의이 답변에는 해당 대안과 관련된 이점이 나열되어 있지 않습니다. 레이아웃은 인라인 된 멤버와 비교하여 중첩 된 구조체 사이에서 다릅니다 (더 많은 패딩이 있습니다. 의도 한 효과 일 수 있지만 일반적으로 단점으로 간주됩니다). –

+0

위에서 주어진 이유 때문에 익명의 '공용체'가 익명의 구조보다 훨씬 유리한 것으로 보입니다. – sherrellbc

1

난 그냥 익명 union의 거대한 이익에 달렸다. 그러나 이것이 희미한 마음을 가진 이야기가 아니며 권장되는 관행임을 경고하십시오.

수백 개의 소스 코드 파일로 이루어진 구형 C 프로그램에는 struct이 구성원으로 포함 된 struct이라는 전역 변수가 있습니다. 다른 사람이 코드가 기록 된 시점에서 STRUCTONE보다 모두 작았 그러나

typedef struct { 
    LONG  lAmount; 
    STRUCTONE largeStruct; // memory area actually used for several different struct objects 
    ULONG  ulFlags; 
} STRUCTCOMMON; 

struct, STRUCTONE는 여러 대형 구조체 중 하나 : 그래서 전역 변수에 대한 형식 정의는 같은 어떤 것을 보았다. 따라서이 메모리 영역 인 largeStructunion으로 사용되고 있지만이를 나타내는 적절한 소스 문이 없습니다. 대신 다양한 struct 변수가 memcpy()을 사용하여이 영역에 복사되었습니다.사태를 악화시키기 위해서는 때로는 전역 변수의 실제 이름을 통해, 때로는 전역 변수를 가리키는 포인터를 통해 이루어졌습니다.

일반적으로 시간이 갈수록 최근의 변경으로 인해 다른 구조체 중 하나가 최대가되었습니다. 그리고 나는이 파일이 여러 가지 별명과 함께 사용되는 곳을 찾는 백개의 파일을 살펴야 만했습니다.

그리고 익명의 노동 조합을 기억했습니다.

typedef struct { 
    LONG  lAmount; 
    union { 
     // anonymous union to allow for allocation of largest space needed 
     STRUCTONE largeStruct; // memory area actually used for several different struct objects 
     STRUCTTHREE largerStruct; // memory area for even larger struct 
    }; 
    ULONG  ulFlags; 
} STRUCTCOMMON; 

을 그리고 모든 것을 다시 컴파일 : 그래서 나는 다음과 같은 일하기 위해 typedef를 수정했습니다.

그래서 이제는 불행히도 기대했던 모든 소스 코드 검토 및 회귀 테스트가 더 이상 필요하지 않습니다.

이제이 글로벌 소스를 사용하여 소스를 천천히 수정하는 과정을 시작하여이 소스를 내 시간 테이블에서보다 최신 표준으로 가져올 수 있습니다.

관련 문제