programing

누가 유니언을 쓰겠어?C-only 시절의 유물인가요?

goodsources 2022. 7. 28. 00:04
반응형

누가 유니언을 쓰겠어?C-only 시절의 유물인가요?

나는 배우기는 했지만 실제로 조합이 생기지는 않는다.C 또는 C++ 텍스트는 모두 소개되지만(때로는 지나가는 경우도 있지만) 그 이유나 사용처에 대한 실제적인 예는 거의 제시하지 않는 경향이 있습니다.현대(또는 유산)의 경우 언제 조합이 유용할 것인가?작업 공간이 매우 한정되어 있거나 API(또는 이와 유사한 것)를 개발하고 있을 때 최종 사용자에게 한 번에 여러 개체/유형의 인스턴스만 사용하도록 강요하고 싶을 때 마이크로프로세서를 프로그래밍하는 것이 유일한 두 가지 추측입니다.이 두 가지 추측이 맞긴 한가요?

결합은 일반적으로 식별자와 함께 사용됩니다. 즉, 결합의 어떤 필드가 유효한지를 나타내는 변수입니다.예를 들어, 독자적인 Variant 타입을 작성한다고 합니다.

struct my_variant_t {
    int type;
    union {
        char char_value;
        short short_value;
        int int_value;
        long long_value;
        float float_value;
        double double_value;
        void* ptr_value;
    };
};

그런 다음 다음과 같이 사용합니다.

/* construct a new float variant instance */
void init_float(struct my_variant_t* v, float initial_value) {
    v->type = VAR_FLOAT;
    v->float_value = initial_value;
}

/* Increments the value of the variant by the given int */
void inc_variant_by_int(struct my_variant_t* v, int n) {
    switch (v->type) {
    case VAR_FLOAT:
        v->float_value += n;
        break;

    case VAR_INT:
        v->int_value += n;
        break;
    ...
    }
}

이것은, 특히 Visual Basic 내부에서는, 꽤 일반적인 관용어입니다.

실제의 예에 대해서는, SDL의 SDL_Event union을 참조해 주세요.(소스코드는 이쪽).이 있습니다.type모든 SDL_*이벤트 구조에서 동일한 필드가 반복됩니다.다음 올바른 는 '보다 낫다'의 .typesyslog.syslog.syslog.

이점은 간단합니다. 불필요한 메모리를 사용하지 않고 모든 이벤트 유형을 처리할 수 있는 단일 데이터 유형이 있습니다.

나는 C++ 조합이 꽤 멋지다고 생각한다.사람들은 보통 유니언 인스턴스의 값을 "적소"로 변경하려는 사용 사례만 생각하는 것 같습니다(메모리를 절약하거나 의심스러운 변환을 수행하는 데만 도움이 되는 것 같습니다.

실제로 유니언 인스턴스의 값을 변경하지 않더라도 소프트웨어 엔지니어링 도구로서 유니언은 큰 힘이 될 수 있습니다.

사용 예 1: 카멜레온

연합을 사용하면 여러 개의 임의의 클래스를 하나의 교단으로 재결합할 수 있습니다.이것은 기본 클래스 및 파생 클래스의 경우와의 유사성이 없는 것은 아닙니다.단, 변경사항은 특정 유니언 인스턴스에서 수행할 수 있는 작업과 수행할 수 없는 작업입니다.

struct Batman;
struct BaseballBat;

union Bat
{
    Batman brucewayne;
    BaseballBat club;
};

ReturnType1 f(void)
{
    BaseballBat bb = {/* */};
    Bat b;
    b.club = bb;
    // do something with b.club
}

ReturnType2 g(Bat& b)
{
    // do something with b, but how do we know what's inside?
}

Bat returnsBat(void);
ReturnType3 h(void)
{
    Bat b = returnsBat();
    // do something with b, but how do we know what's inside?
}

프로그래머는 특정 유니언인스턴스를 사용하고 싶을 때 콘텐츠의 종류를 확인해야 합니다.으로는 f인수로 , 를 들어 「」의 ,g됩니다.를 참조해 주세요.를 참조해 주십시오.h: 그 알 수 발신자는 어떻게 안에 무엇이 있는지 알 수 있습니까?

유니언 인스턴스가 인수나 반환값으로 전달되지 않으면 프로그래머가 내용을 바꾸기로 선택했을 때 흥분과 함께 매우 단조로운 삶을 살게 됩니다.

Batman bm = {/* */};
Baseball bb = {/* */};
Bat b;
b.brucewayne = bm;
// stuff
b.club = bb;

그리고 그것이 조합의 가장 인기 있는 사용 사례입니다.또 다른 사용 사례는 유니언 인스턴스가 그 유형을 알려주는 어떤 것과 함께 제공되는 경우입니다.

사용 사례 2: "반갑습니다. 저는object에서, syslogsClass

어떤 프로그래머가 유니언 인스턴스를 항상 유형 기술자와 쌍을 이루도록 선택했다고 가정합니다(이러한 오브젝트의 구현을 상상하는 것은 독자의 재량에 맡기겠습니다).프로그래머가 메모리를 절약하고 타입 기술자의 사이즈가 유니언의 사이즈에 비해 무시할 수 없는 것이 아닌 경우, 이것은 유니언 자체의 목적을 저하시킨다.단, 유니언인스턴스가 인수 또는 반환값으로 전달될 수 있는 것이 착신측 또는 발신측이 그 내용을 모르는 경우에 중요하다고 가정합니다.

는 A를 .switch브루스 웨인을 나무 막대기와 구별하기 위한 제어 흐름 문입니다.조합에 콘텐츠가 두 종류밖에 없는 것도 나쁘지 않지만, 분명히 조합은 더 이상 확장되지 않는다.

사용 예 3:

ISO C++ 표준에 대한 권장사항의 저자가 2008년에 언급했듯이,

많은 중요한 문제 도메인에는 많은 수의 개체가 필요하거나 제한된 메모리 리소스가 필요합니다.이런 상황에서는 공간을 절약하는 것이 매우 중요하며, 종종 결합이 그것을 위한 완벽한 방법이다.사실, 일반적인 사용 사례는 노조가 생전에 활동 중인 조합원을 절대 바꾸지 않는 상황입니다.하나의 부재만을 포함하는 구조인 것처럼 구성, 복사 및 파괴할 수 있습니다.일반적으로는 동적으로 할당되지 않은 관련되지 않은 유형의 이기종 컬렉션을 작성하는 것입니다(아마 맵 또는 어레이의 멤버로 구성되었을 수 있습니다).

다음으로 UML 클래스 다이어그램의 예를 제시하겠습니다.

클래스 A의 많은 작곡

쉬운 영어의 상황: 클래스 A의 오브젝트는 B1, ..., Bn 중 어느 클래스의 오브젝트를 가질 수 있습니다.또한 각 타입의 오브젝트 중 적어도1개(n은 꽤 큰 숫자)는 10개입니다.

다음과 같이 A에 필드(데이터 멤버)를 추가하고 싶지 않습니다.

private:
    B1 b1;
    .
    .
    .
    Bn bn;

n은 다를 수 있습니다(혼합에 Bx 클래스를 추가할 수 있습니다).또한 컨스트럭터와 혼동이 발생하여 A 객체가 많은 공간을 차지하기 때문입니다.

괴상한 컨테이너가 필요할 수도 있고void*입니다.Bx은 관리해야 것입니다.그러나 더 중요한 것은 동적으로 할당된 많은 개체의 수명을 관리할 수 있다는 점입니다.

대신 할 수 있는 일은 다음과 같습니다.

union Bee
{
    B1 b1;
    .
    .
    .
    Bn bn;
};

enum BeesTypes { TYPE_B1, ..., TYPE_BN };

class A
{
private:
    std::unordered_map<int, Bee> data; // C++11, otherwise use std::map

public:
    Bee get(int); // the implementation is obvious: get from the unordered map
};

다음 음음음음음음음음 from from from from from from from from from from from from from from from from from from from 에서 유니언 의 내용을 얻으려면data , 을합니다.a.get(TYPE_B2).b2여기서 등, 디, 디, 디, 。aA★★★★★★ 。

C++11에서는 노조가 무제한이기 때문에 이것은 더욱 강력하다.자세한 내용은 의 링크 문서 또는 문서참조하십시오.

유니언의 일부 용도:

  • 알 수 없는 외부 호스트에 일반 엔디안니스 인터페이스를 제공합니다.
  • 네트워크 링크에서 VAX G_FLOATS를 받아들여 처리를 위해 IEEE 754 long real로 변환하는 등 외부 CPU 아키텍처 부동소수점 데이터를 조작합니다.
  • 더 높은 수준의 유형에 대한 간단한 비트 트위들링 액세스를 제공합니다.
union {
      unsigned char   byte_v[16];
      long double     ld_v;
 }

값을 할 수 .long double지수 기호를 변경하거나, 지수 기호가 정규값인지 여부를 확인하거나, 이를 지원하지 않는 CPU에 대해 긴 이중 산술을 구현하는 등의 작업을 수행합니다.

  • 필드가 특정 값에 종속된 경우 저장소 공간 절약:

    class person {  
        string name;  
    
        char gender;   // M = male, F = female, O = other  
        union {  
            date  vasectomized;  // for males  
            int   pregnancies;   // for females  
        } gender_specific_data;
    }
    
  • GREP를 포함하다union:

    [wally@zenetfedora ~]$ cd /usr/include
    [wally@zenetfedora include]$ grep -w union *
    a.out.h:  union
    argp.h:   parsing options, getopt is called with the union of all the argp
    bfd.h:  union
    bfd.h:  union
    bfd.h:union internal_auxent;
    bfd.h:  (bfd *, struct bfd_symbol *, int, union internal_auxent *);
    bfd.h:  union {
    bfd.h:  /* The value of the symbol.  This really should be a union of a
    bfd.h:  union
    bfd.h:  union
    bfdlink.h:  /* A union of information depending upon the type.  */
    bfdlink.h:  union
    bfdlink.h:       this field.  This field is present in all of the union element
    bfdlink.h:       the union; this structure is a major space user in the
    bfdlink.h:  union
    bfdlink.h:  union
    curses.h:    union
    db_cxx.h:// 4201: nameless struct/union
    elf.h:  union
    elf.h:  union
    elf.h:  union
    elf.h:  union
    elf.h:typedef union
    _G_config.h:typedef union
    gcrypt.h:  union
    gcrypt.h:    union
    gcrypt.h:    union
    gmp-i386.h:  union {
    ieee754.h:union ieee754_float
    ieee754.h:union ieee754_double
    ieee754.h:union ieee854_long_double
    ifaddrs.h:  union
    jpeglib.h:  union {
    ldap.h: union mod_vals_u {
    ncurses.h:    union
    newt.h:    union {
    obstack.h:  union
    pi-file.h:  union {
    resolv.h:   union {
    signal.h:extern int sigqueue (__pid_t __pid, int __sig, __const union sigval __val)
    stdlib.h:/* Lots of hair to allow traditional BSD use of `union wait'
    stdlib.h:  (__extension__ (((union { __typeof(status) __in; int __i; }) \
    stdlib.h:/* This is the type of the argument to `wait'.  The funky union
    stdlib.h:   causes redeclarations with either `int *' or `union wait *' to be
    stdlib.h:typedef union
    stdlib.h:    union wait *__uptr;
    stdlib.h:  } __WAIT_STATUS __attribute__ ((__transparent_union__));
    thread_db.h:  union
    thread_db.h:  union
    tiffio.h:   union {
    wchar.h:  union
    xf86drm.h:typedef union _drmVBlank {
    

Herb Sutter는 약 6년 전 GOTW에서 다음과 같이 강조를 덧붙였습니다.

그는 그러나 노조가 예전의 유보일 뿐이라고 생각하지 않는다.데이터 중복을 허용함으로써 공간을 절약하는 데 조합이 가장 유용할 수 있으며, 는 C++와 오늘날의 세계에서도 여전히 바람직합니다.예를 들어, 현재 세계에서 가장 고도의 C++ 표준 라이브러리 구현 중 일부는 문자열 개체 자체의 스토리지를 재사용하는 훌륭한 최적화 대안인 "작은 문자열 최적화"를 구현하기 위해 이 기술만 사용합니다. 큰 문자열의 경우 문자열 개체 내부 공간에 동적으로 대한 일반적인 포인터가 저장됩니다.버퍼 및 버퍼 크기 등의 하우스키핑 정보가 할당되어 있습니다.작은 문자열의 경우 대신 같은 공간이 문자열 내용을 직접 저장하기 위해 재사용되어 동적 메모리 할당을 완전히 방지합니다.작은 문자열 최적화(및 기타 문자열 최적화 및 비관화)에 대한 자세한 내용은..."를 참조하십시오.

그리고 덜 유용한 예로는 gcc, 엄격한 에일리어싱 및 유니언을 통한 캐스팅을 참조하십시오.

예를 들어 다음과 같은 사용 사례를 생각할 수 있습니다.

typedef union
{
    struct
    {
        uint8_t a;
        uint8_t b;
        uint8_t c;
        uint8_t d;
    };
    uint32_t x;
} some32bittype;

그런 다음 32비트 데이터 블록의 8비트 개별 부분에 액세스할 수 있습니다. 단, 엔디안니스에 감염될 가능성에 대비하십시오.

이것은 하나의 가설적인 예에 불과하지만 필드의 데이터를 이와 같은 구성 요소로 분할하려면 항상 결합을 사용할 수 있습니다.

단, 엔디안 세이프한 방법도 있습니다.

uint32_t x;
uint8_t a = (x & 0xFF000000) >> 24;

예를 들어, 이 바이너리 연산은 컴파일러에 의해 올바른 엔디안니스로 변환되기 때문입니다.

예를 들어 레지스터의 각 비트가 다른 것을 의미할 수 있는 임베디드 렐름입니다.예를 들어 8비트 정수와 8개의 개별 1비트 필드가 있는 구조를 조합하면 1비트 또는 전체 바이트를 변경할 수 있습니다.

결합은 C에서 다형성을 제공한다.

union키워드는 C++03에서도1 사용되고 있습니다만, 대부분의 경우 C일의 나머지입니다.가장 큰 문제는 POD에서만1 작동한다는 것입니다.

그러나 유니언의 개념은 여전히 존재하며, 실제로 Boost 라이브러리는 유니언과 같은 클래스를 특징으로 합니다.

boost::variant<std::string, Foo, Bar>

이 가장 큰 수중에 .union는 아닌 ) 및 과 같이 추가합니다

  • 비POD 유형을 올바르게 사용할 수 있는 능력
  • 정적 안전

은 제, 음, 음, 음, 음, 음, 음, 음, 는, 는, 는, 는, 는, 는, 는, 는, in, in, in, in, in, in, in, in, in, in, in, in, in, , in, in, in,union+enum그리고, 그 속도가 같은 것을 벤치마킹했습니다(대부분의 경우).boost::any의 영역에 가깝다.dynamic_castRTI r 、 [ RTI ])

유니언은 C++11(제한되지 않은 유니언)1로 업그레이드되어 디스트럭터가 있는 오브젝트를 포함할 수 있게 되었습니다.다만, 유저는 디스트럭터를 수동으로 기동할 필요가 있습니다(현재 액티브한 유니언 멤버로).변종을 사용하는 것이 훨씬 더 쉽습니다.

C의 초창기(1974년에 문서화된 것처럼)에는 모든 구조물이 구성원을 위한 공통 네임스페이스를 공유했다. 있습니다.에서 " "가 .'wd_wozle'은 'int'는 'int'는 'int'는 12개입니다.p 유형, "구조 유형", " 유형"p->wd_woozle 동등하다*(int*)(((char*)p)+12)사용된 모든 구조가 공통의 초기 시퀀스로 취급되는 경우 멤버 이름을 명시적으로 재사용할 수 있는 것을 제외하고 모든 구조 유형의 모든 멤버가 고유한 이름을 가져야 하는 언어입니다.

구조 유형을 혼합적으로 사용할 수 있기 때문에 구조가 겹치는 필드를 포함하는 것처럼 동작할 수 있습니다.예를 들어 다음과 같은 정의가 있습니다.

struct float1 { float f0;};
struct byte4  { char b0,b1,b2,b3; }; /* Unsigned didn't exist yet */

코드는 타입 "disclos1"의 구조를 선언하고 "members" b0...을 사용할 수 있습니다.b3를 사용하여 각각의 바이트에 있는 각 바이트에 액세스 합니다.각 구조가 멤버를 위해 별도의 네임스페이스를 받도록 언어가 변경되면 여러 가지 방법으로 액세스할 수 있는 능력에 의존하는 코드가 깨집니다.다른 구조 유형에 대해 네임스페이스를 분리하는 값은 그러한 코드를 변경하도록 요구하기에 충분했지만, 그러한 기술의 가치는 언어를 계속 지원하도록 확장하는 것을 정당화하기에 충분했다.

내부 스토리지에 액세스하는 기능을 이용하기 위해 작성된 코드struct float1 …인 struct byte4는 새로운 할 수 .union f1b4 { struct float1 ff; struct byte4 bb; };union f1b4;struct float1f0,b0,b1등를 사용합니다.ff.f0,bb.b0,bb.b1될 수 더 , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,union접근법은 적어도 C89 시대의 에일리어싱 규칙 해석과 함께 어느 정도 실행 가능했다.

유니언의 훌륭한 용도는 PCL(Point Cloud Library) 소스코드에서 찾은 메모리 얼라인먼트입니다.API의 단일 데이터 구조는 SSE를 지원하는 CPU와 SSE를 지원하지 않는 CPU의 두 가지 아키텍처를 대상으로 할 수 있습니다.예: PointX의 데이터 구조YZ는

typedef union
{
  float data[4];
  struct
  {
    float x;
    float y;
    float z;
  };
} PointXYZ;

3개의 플로트는 SSE 정렬을 위해 추가 플로트로 패딩되어 있습니다.그러니까

PointXYZ point;

사용자는 x 좌표에 액세스하기 위해 point.data[0] 또는 point.x(SSE 지원에 따라 다름)에 액세스 할 수 있습니다.더 나은 사용방법에 대한 자세한 내용은 PCL documentation PointT types 링크를 참조하십시오.

결합은 바이트 수준(낮은 수준) 데이터를 처리할 때 유용합니다.

최근에 사용한 것 중 하나는 다음과 같은 IP 주소 모델링이었습니다.

// Composite structure for IP address storage
union
{
    // IPv4 @ 32-bit identifier
    // Padded 12-bytes for IPv6 compatibility
    union
    {
        struct
        {
            unsigned char _reserved[12];
            unsigned char _IpBytes[4];
        } _Raw;

        struct
        {
            unsigned char _reserved[12];
            unsigned char _o1;
            unsigned char _o2;
            unsigned char _o3;
            unsigned char _o4;    
        } _Octet;    
    } _IPv4;

    // IPv6 @ 128-bit identifier
    // Next generation internet addressing
    union
    {
        struct
        {
            unsigned char _IpBytes[16];
        } _Raw;

        struct
        {
            unsigned short _w1;
            unsigned short _w2;
            unsigned short _w3;
            unsigned short _w4;
            unsigned short _w5;
            unsigned short _w6;
            unsigned short _w7;
            unsigned short _w8;   
        } _Word;
    } _IPv6;
} _IP;

유니언을 사용한 예:

class Vector
{
        union 
        {
            double _coord[3];
            struct 
            {
                double _x;
                double _y; 
                double _z;
            };

        };
...
}

이를 통해 어레이 또는 요소로 데이터에 액세스할 수 있습니다.

나는 다른 용어들이 같은 값을 가리키도록 하기 위해 결합체를 사용했다.화상 처리에서는, 세로줄이나 가로폭, X방향의 사이즈에 관계없이, 혼란이 생깁니다.이 문제를 해결하기 위해 저는 유니언을 사용하기 때문에 어떤 표현이 어울리는지 알 수 있습니다.

   union {   // dimension from left to right   // union for the left to right dimension
        uint32_t            m_width;
        uint32_t            m_sizeX;
        uint32_t            m_columns;
    };

    union {   // dimension from top to bottom   // union for the top to bottom dimension
        uint32_t            m_height;
        uint32_t            m_sizeY;
        uint32_t            m_rows;
    };

조합에 관한 위키피디아 기사:

유니언의 주된 유용성은 공간을 절약하는 것이다. 왜냐하면 유니언은 같은 공간에 많은 다른 유형을 저장할 수 있는 방법을 제공하기 때문이다.조합은 또한 조잡한 다형성을 제공한다.다만, 타입의 체크는 행해지지 않기 때문에, 적절한 필드가 다른 컨텍스트에서 액세스 되고 있는 것을 확인하는 것은 프로그래머에게 달려 있습니다.결합 변수의 관련 필드는 일반적으로 다른 변수의 상태에 의해 결정되며, 아마도 주변 구조에서 결정될 수 있다.

하나의 일반적인 C 프로그래밍 관용구는 값의 원시 표현에 의존하는 코드에서처럼 C++가 유니언의 한 필드에 할당하고 다른 필드에서 읽어냄으로써 C++가 재해석_cast라고 부르는 것을 실행하기 위해 유니언을 사용한다.

n개의 다른 유형의 구성이 있다고 가정합니다(파라미터 정의 변수 세트일 뿐입니다).설정 타입의 열거를 사용하면, 설정 타입의 ID 와 모든 다른 타입의 설정을 조합하는 구조를 정의할 수 있습니다.

이렇게 하면 Configuration을 통과하는 모든 장소에서 ID를 사용하여 Configuration 데이터를 해석하는 방법을 결정할 수 있지만 Configuration이 클 경우 공간이 낭비될 수 있는 유형별로 병렬 구조를 가질 필요가 없습니다.

이미 높아진 조합의 중요성에 대한 최근 한 가지 부상은 C 표준의 최근 버전에서 도입된 엄격한 별칭 규칙에 의해 주어졌다.

조합 방식을 사용하여 C 표준을 위반하지 않고 타이핑할 수 있습니다.
이 프로그램에는 지정되지 않은 동작이 있습니다(그 이유는 다음과 같습니다).float ★★★★★★★★★★★★★★★★★」unsigned int길이가 동일하지만 정의되지 않은 동작(여기를 참조).

#include <stdio.h> 

union float_uint
{
    float f;
    unsigned int ui;
};

int main()
{
    float v = 241;
    union float_uint fui = {.f = v};

    //May trigger UNSPECIFIED BEHAVIOR but not UNDEFINED BEHAVIOR 
    printf("Your IEEE 754 float sir: %08x\n", fui.ui);

    //This is UNDEFINED BEHAVIOR as it violates the Strict Aliasing Rule
    unsigned int* pp = (unsigned int*) &v;

    printf("Your IEEE 754 float, again, sir: %08x\n", *pp);

    return 0;
}

저는 합집합 사용의 좋은 실례를 하나 추가하고자 합니다. 즉, 계산식 계산기/통역기를 구현하거나 계산에서 어떤 종류의 계산기를 사용하는 입니다(예를 들어, 계산식의 런타임 부분(예를 들어 방정식을 수치적으로 푸는 것 등).따라서 다음과 같이 다양한 유형(정수, 부동 소수점, 심지어 복소수)의 숫자/상수를 정의할 수 있습니다.

struct Number{
enum NumType{int32, float, double, complex}; NumType num_t;
union{int ival; float fval; double dval; ComplexNumber cmplx_val}
}

따라서 메모리를 절약하고 더 중요한 것은 (클래스 상속/다형성을 통한 구현과 비교하여 런타임에 정의된 많은 수를 사용하는 경우) 아마도 매우 많은 수의 작은 개체에 대해 동적 할당을 피해야 한다는 것입니다.더 흥미로운 것은 C++다형성(예를 들어 더블 디스패치 팬)의 파워를 이 타입의 구조에서도 사용할 수 있다는 것입니다.이 구조체의 필드로서 모든 번호 유형의 부모 클래스에 "dummy" 인터페이스 포인터를 추가하거나 raw 타입이 아닌 이 인스턴스를 가리키거나 오래된 C 함수 포인터를 사용하십시오.

struct NumberBase
{
virtual Add(NumberBase n);
...
}
struct NumberInt: Number
{
//implement methods assuming Number's union contains int
NumberBase Add(NumberBase n);
...
}
struct NumberDouble: Number
{
 //implement methods assuming Number's union contains double
 NumberBase Add(NumberBase n);
 ...
}
//e.t.c. for all number types/or use templates
struct Number: NumberBase{
 union{int ival; float fval; double dval; ComplexNumber cmplx_val;}
 NumberBase* num_t;
 Set(int a)
 {
 ival=a;
  //still kind of hack, hope it works because derived classes of   Number    dont add any fields
 num_t = static_cast<NumberInt>(this);
 }
}

따라서 필요에 따라 스위치(타입)에서 타입 체크 대신 메모리 효율이 뛰어난 실장(작은 오브젝트의 동적 할당 없음)을 사용하여 다형성을 사용할 수 있습니다.

http://cplus.about.com/od/learningc/ss/lowlevel_9.htm 에서 :

결합의 용도는 극히 드물다.대부분의 컴퓨터에서는 포인터와 int의 사이즈가 같은 것이 일반적입니다.이것은 보통 양쪽이 CPU의 레지스터에 들어가 있기 때문입니다.따라서 int에 대한 포인터의 빠르고 더러운 캐스트를 하고 싶다면 유니언을 선언합니다.

union intptr {   int i;   int * p; }; 
union intptr x; x.i = 1000; 
/* puts 90 at location 1000 */ 
*(x.p)=90; 

유니언의 또 다른 용도는 다양한 크기의 메시지를 보내고 받는 명령 또는 메시지 프로토콜입니다.각 메시지 유형에는 서로 다른 정보가 저장되지만, 각 메시지 유형에는 고정 부품(아마도 구조)과 가변 부품 비트가 있습니다.다음과 같이 구현할 수 있습니다.

struct head {   int id;   int response;   int size; }; struct msgstring50 {    struct head fixed;    char message[50]; } struct

{ fixed ; message [ ] ; slocks msgstring80 { structure head fixed ; char message [ 80 ] ; }
{ fixed ;message [ ] ; } msgack { fixed ;ok ; } structure msgack { structure head fixed ;int } structure msgack { structure head fixed ;int } 유니언 유형 structure }
msgstring 50 structure 80 structure structure ack, } structure msgstring 50 m50, structure msgstring 80 m80, structure msgack, }

실제로는 조합의 규모는 동일하지만 공간을 낭비하지 않고 의미 있는 데이터만 전송하는 것이 타당합니다.msgack은 16바이트에 불과하지만 msgstring80은 92바이트입니다.따라서 메시지 유형 변수가 초기화되면 해당 변수 유형에 따라 크기 필드가 설정됩니다.그러면 다른 함수가 올바른 바이트 수를 전송하기 위해 사용할 수 있습니다.

유니언은 프로그램에 기계에 의존하지 않는 정보를 포함하지 않고 단일 스토리지 영역에서 다양한 종류의 데이터를 조작할 수 있는 방법을 제공합니다. 파스칼의 변형 레코드와 유사합니다.

컴파일러 심볼 테이블 매니저에서 볼 수 있는 예로서 상수가 int, float 또는 문자 포인터라고 가정합니다.특정 상수의 값은 적절한 유형의 변수에 저장해야 하지만, 값이 동일한 양의 저장 공간을 차지하고 유형에 관계없이 동일한 위치에 저장되는 경우 테이블 관리에 가장 편리합니다.이것이 결합의 목적입니다. 즉, 여러 유형 중 하나를 합법적으로 보유할 수 있는 단일 변수입니다.구문은 구조에 기초하고 있습니다.

union u_tag {
     int ival;
     float fval;
     char  *sval;
} u;

변수 u는 3가지 유형 중 가장 큰 유형을 포함할 수 있을 정도로 커집니다.특정 크기는 구현에 따라 달라집니다.사용방법에 일관성이 있는 한 이러한 유형을 u에 할당하여 식에 사용할 수 있습니다.

언급URL : https://stackoverflow.com/questions/4788965/when-would-anyone-use-a-union-is-it-a-remnant-from-the-c-only-days

반응형