언제 노조를 사용하겠습니까? C- 전용 날의 잔재입니까?
나는 배웠지 만 실제로 노동 조합을 얻지는 못한다. 내가 통과하는 모든 C 또는 C ++ 텍스트는 그것들을 소개하지만 (때로는 통과 할 때도 있지만) 왜 또는 어디에서 사용해야하는지에 대한 실제적인 예는 거의 없습니다. 현대 (또는 레거시) 사례에서 노동 조합은 언제 유용할까요? 내 유일한 두 가지 추측은 작업 할 공간이 매우 제한적이거나 API (또는 비슷한 것)를 개발할 때 최종 사용자가 여러 객체 / 유형의 인스턴스를 하나만 갖도록하려는 경우 마이크로 프로세서를 프로그래밍하는 것입니다. 한 번. 이 두 가지 추측이 오른쪽에 가깝습니까?
노동 조합은 일반적으로 차별 자의 회사와 함께 사용됩니다. 노동 조합의 어느 분야가 유효한지를 나타내는 변수입니다. 예를 들어, 고유 한 변형 유형 을 생성한다고 가정 해 보겠습니다 .
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_ * 이벤트 구조체에 반복됩니다. 그런 다음 올바른 이벤트를 처리하려면 type
필드 값을 확인해야 합니다.
장점은 간단합니다. 불필요한 메모리를 사용하지 않고 모든 이벤트 유형을 처리 할 수있는 단일 데이터 유형이 있습니다.
C ++ 공용체가 꽤 멋지다는 것을 알았습니다. 사람들은 일반적으로 "제자리에서"통합 인스턴스의 값을 변경하려는 유스 케이스 만 생각하는 것 같습니다 (메모리를 절약하거나 의심스러운 변환을 수행하는 데만 도움이 됨).
실제로 Union 인스턴스의 가치를 절대로 변경하지 않더라도 Union 은 소프트웨어 엔지니어링 도구로서 큰 힘을 발휘할 수 있습니다 .
사용 사례 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
부터 Class
"
프로그래머가 유니언 인스턴스를 항상 타입 디스크립터와 짝짓기로 선택했다고 가정 해 보자 (그러한 객체에 대한 구현을 상상하기 위해 독자의 재량에 맡기겠다). 이것은 프로그래머가 원하는 것이 메모리를 절약하고 타입 디스크립터의 크기가 유니온의 크기와 관련하여 무시할 수없는 경우 유니온 자체의 목적을 무효화합니다. 그러나 통합 인스턴스가 내부에 무엇이 있는지 모르는 수신자 또는 호출자에게 인수 또는 반환 값으로 전달 될 수 있어야한다고 가정 해 봅시다.
그런 다음 프로그래머는 switch
Bruce Wayne에게 나무 막대기 또는 이와 동등한 것을 구별하기 위해 제어 흐름 설명을 작성해야합니다. 노조에 두 가지 유형의 내용 만있을 때 그리 나쁘지는 않지만 분명히 노조는 더 이상 확장되지 않습니다.
사용 사례 3 :
ISO C ++ 표준 에 대한 권장 사항 작성자가 2008 년에 다시 제안한 것처럼,
많은 중요한 문제 도메인에는 많은 수의 객체 또는 제한된 메모리 리소스가 필요합니다. 이러한 상황에서 공간 보존은 매우 중요하며, 노조가 종종이를 수행하는 완벽한 방법입니다. 실제로 일반적인 유스 케이스는 노조가 수명 동안 활성 멤버를 변경하지 않는 상황입니다. 마치 하나의 멤버 만 포함 된 구조체 인 것처럼 구성, 복사 및 제거 할 수 있습니다. 이것의 전형적인 적용은 동적으로 할당되지 않은 이종의 비 관련 유형의 콜렉션을 작성하는 것입니다 (아마도 이들은 맵 또는 배열의 멤버로 제자리에 구성되어있을 것입니다).
이제 UML 클래스 다이어그램을 사용한 예제가 있습니다.
일반 영어로 된 상황 : 클래스 A의 객체는 B1, ..., Bn 사이의 모든 클래스의 객체를 가질 수 있으며 각 유형 중 최대 하나는 n 이 10 이상인 꽤 큰 숫자입니다.
다음과 같이 필드 (데이터 멤버)를 A에 추가하고 싶지 않습니다.
private:
B1 b1;
.
.
.
Bn bn;
n 이 다를 수 있기 때문에 (믹스에 Bx 클래스를 추가하고 싶을 수도 있음) 생성자와 혼동을 일으키고 A 객체가 많은 공간을 차지하기 때문입니다.
우리는 캐스트 void*
가있는 Bx
객체 에 대한 포인터 의 이상한 컨테이너를 사용 하여 객체를 검색 할 수는 있지만 모호하고 C 스타일입니다 ... 그러나 더 중요한 것은 동적으로 할당 된 많은 객체의 수명을 관리 할 수있게 해줍니다.
대신 수행 할 수있는 작업은 다음과 같습니다.
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
};
그런 다음에서 노조 인스턴스의 컨텐츠를 얻기 위해 data
당신이 사용 a.get(TYPE_B2).b2
하고 좋아하는, a
클래스입니다 A
인스턴스를.
C ++ 11에서는 공용체가 제한되지 않기 때문에 이것이 더 강력합니다. 자세한 내용 은 위의 문서 또는 이 기사 에 연결된 문서 를 참조하십시오.
하나의 예는 임베디드 영역에 있으며, 레지스터의 각 비트는 다른 의미를 가질 수 있습니다. 예를 들어, 8 비트 정수와 8 개의 개별 1 비트 비트 필드가있는 구조체를 결합하면 하나의 비트 또는 전체 바이트를 변경할 수 있습니다.
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;
예를 들어, 이진 연산은 컴파일러에 의해 올바른 엔디안으로 변환됩니다.
유니언은 바이트 수준 (낮은 수준) 데이터를 처리 할 때 유용합니다.
최근 사용 된 것 중 하나는 다음과 같은 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;
노동 조합에 대한 일부 용도 :
- 알 수없는 외부 호스트에 일반 엔디안 인터페이스를 제공하십시오.
- 네트워크 링크에서 VAX G_FLOATS 를 수락 하고 처리 를 위해 IEEE 754 long reals 로 변환하는 것과 같은 외부 CPU 아키텍처 부동 소수점 데이터를 조작 합니다 .
- 더 높은 수준의 유형에 대한 간단한 비트 트위들 링 액세스를 제공합니다.
union { unsigned char byte_v[16]; long double ld_v; }
이 선언을 사용하면 a의 16 진수 바이트 값을 표시하거나
long double
지수 기호를 변경하거나 비정규 값인지 확인하거나 지원하지 않는 CPU에 대해 긴 이중 산술을 구현하는 등의 작업이 간단합니다 .
필드가 특정 값에 종속되는 경우 저장 공간 절약 :
class person { string name; char gender; // M = male, F = female, O = other union { date castrated; // for males int pregnancies; // for females } gender_specific_data; }
컴파일러에서 사용할 포함 파일을 정리하십시오. 수십에서 수백 가지 용도로 사용됩니다
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 {
유니온을 사용한 경우의 예 :
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는 다형성을 제공합니다.
통합의 훌륭한 사용법은 PCL (Point Cloud Library) 소스 코드에서 찾은 메모리 정렬입니다. API의 단일 데이터 구조는 SSE를 지원하는 CPU와 SSE를 지원하지 않는 CPU의 두 가지 아키텍처를 대상으로 할 수 있습니다. 예를 들어 : PointXYZ의 데이터 구조는
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 문서 PointT 유형
union
여전히 ++ C에서 03 사용하면서 키워드, 1 , 주로 C 일의 잔재입니다. 가장 눈에 띄는 문제는 POD 1 에서만 작동한다는 것 입니다.
그러나 노조에 대한 아이디어는 여전히 존재하며 실제로 Boost 라이브러리에는 노조와 같은 클래스가 있습니다.
boost::variant<std::string, Foo, Bar>
union
(모두가 아닐지라도) 장점의 대부분을 가지고 있으며 다음을 추가합니다.
- 비 포드 유형을 올바르게 사용하는 기능
- 정적 안전
실제로, 그것은 union
+ 의 조합과 동등한 것으로 입증되었으며, 그것이 enum
빠른 것으로 벤치마킹했습니다 ( RTTI를 사용하기 때문에 boost::any
더 많은 영역입니다 dynamic_cast
).
1 Union은 C ++ 11 ( 제한되지 않은 union ) 에서 업그레이드되었으며 , 사용자는 현재 활성 Union 멤버에서 소멸자를 수동으로 호출해야하지만 소멸자가있는 객체를 포함 할 수 있습니다. 변형을 사용하는 것이 훨씬 쉽습니다.
노조에 관한 Wikipedia 기사에서 :
공용체의 주요 유용성은 공간 을 절약하는 것입니다. 공간 을 절약 할 수 있기 때문에 여러 유형을 같은 공간에 저장할 수 있습니다. 연합은 또한 조 다형성을 제공합니다 . 그러나 유형을 확인하지 않으므로 다른 필드에서 올바른 필드에 액세스해야하는 것은 프로그래머의 책임입니다. 공용체 변수의 관련 필드는 일반적으로 다른 변수의 상태에 의해, 가능하면 둘러싸는 구조체에서 결정됩니다.
하나의 공통 C 프로그래밍 관용구는 공용체를 사용하여 값의 원시 표현에 의존하는 코드에서와 같이 공용체의 한 필드에 할당하고 다른 필드에서 읽음으로써 reinterpret_cast를 호출하는 것을 수행합니다.
n 가지 유형의 구성이 있다고 가정 해 봅시다 (매개 변수를 정의하는 변수 세트 일뿐입니다). 구성 유형의 열거를 사용하여 구성 유형의 ID를 가진 다른 모든 유형의 구성을 통합 한 구조를 정의 할 수 있습니다.
이 방법으로 구성을 전달할 때마다 ID를 사용하여 구성 데이터를 해석하는 방법을 결정할 수 있지만 구성이 큰 경우 각 잠재적 유형 낭비 공간에 대해 병렬 구조를 갖지 않아도됩니다.
최근 에 C 표준의 최신 버전에 도입 된 엄격한 앨리어싱 규칙에 의해 노조 의 중요성이 높아지고 최근에 한 가지 향상 이 이루어졌습니다 .
C 표준을 위반하지 않고 공용체 do를 사용하여 유형 정리 를 할 수 있습니다 .
이 프로그램은이 지정되지 않은 행동을 (내가 가정 때문에 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 ++ 다형성의 힘을 사용할 수 있습니다 (예 : 이중 디스패치의 팬이라면). 모든 숫자 유형의 부모 클래스에 "더미"인터페이스 포인터를이 구조체의 필드 로 추가하고 원시 유형 대신 / 이 인스턴스 를 가리 키 거나 기존 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);
}
}
따라서 스위치 (유형)-메모리 효율적인 구현 (작은 객체의 동적 할당 없음)-유형 검사 대신 다형성을 사용할 수 있습니다 (필요한 경우).
C의 초창기 (예 : 1974 년에 문서화 됨)에 모든 구조는 해당 멤버의 공통 네임 스페이스를 공유했습니다. 각 멤버 이름은 유형 및 오프셋과 연관되었습니다. "wd_woozle"이 오프셋 12에서 "int" p
인 경우 모든 구조 유형 의 포인터 가 주어지면 다음 p->wd_woozle
과 같습니다 *(int*)(((char*)p)+12)
. 언어는 모든 구조 유형의 모든 구성원이 고유 한 이름을 가지고 요구 를 제외하고 는 명시 적으로 사용 된 모든 구조체가 공통의 초기 시퀀스로 취급 경우 멤버 이름의 재사용을 허용하는.
구조 유형을 무차별 적으로 사용할 수 있다는 사실은 구조가 겹치는 필드를 포함하는 것처럼 동작하도록하는 것을 가능하게했습니다. 예를 들어, 주어진 정의 :
struct float1 { float f0;};
struct byte4 { char b0,b1,b2,b3; }; /* Unsigned didn't exist yet */
코드는 "float1"유형의 구조를 선언 한 다음 "members"b0 ... b3을 사용하여 개별 바이트에 액세스 할 수 있습니다. 각 구조가 멤버에 대해 별도의 네임 스페이스를 받도록 언어가 변경되면 여러 가지 방식으로 액세스 할 수있는 기능에 의존하는 코드가 작동하지 않습니다. 서로 다른 구조 유형에 대해 네임 스페이스를 분리하는 값은 그러한 코드를 수용하기 위해 변경되도록 요구하기에 충분했지만 그러한 기술의 가치는 언어를 계속 지원하기 위해 언어를 확장하는 것을 정당화하기에 충분했습니다.
내에서 스토리지를 액세스 할 수있는 기능을 이용하기 위해 작성했던 코드 struct float1
그것이 것처럼 struct byte4
: 선언을 추가하여 새로운 언어로 작동하도록 만들 수 있습니다 union f1b4 { struct float1 ff; struct byte4 bb; };
, 선언 객체 유형으로 union f1b4;
보다는 struct float1
, 그리고에 액세스 교체 f0
, b0
, b1
, 등 .와 ff.f0
, bb.b0
, bb.b1
같은 코드가 지원 될 수 있었다 더 나은 방법이 있지만, 등의 union
접근 방식은 적어도 앨리어싱 규칙 C89 시대의 해석과, 적어도 어느 정도 가능한이었다.
에서 http://cplus.about.com/od/learningc/ss/lowlevel_9.htm :
노조의 사용은 거의 없으며 그 사이에 있습니다. 대부분의 컴퓨터에서 포인터와 int의 크기는 일반적으로 동일합니다. 이는 일반적으로 CPU의 레지스터에 맞기 때문입니다. 따라서 int 또는 다른 방법으로 포인터를 빠르고 더러운 캐스트하려면 Union을 선언하십시오.
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
struct msgstring80 {구조체 헤드 고정; 문자 메시지 [80]; }
struct msgint10 {구조체 헤드 고정; int 메시지 [10]; } 구조체 msgack {구조체 헤드 고정; int ok; } 통합 메시지 유형 {
struct msgstring50 m50; 구조체 msgstring80 m80; 구조체 msgint10 i10; 구조체 msgack ack; }실제로, 공용체의 크기는 동일하지만 공간을 낭비하지 않고 의미있는 데이터 만 전송하는 것이 좋습니다. msgack의 크기는 16 바이트이고 msgstring80의 크기는 92 바이트입니다. 따라서 메시지 유형 변수가 초기화되면 유형에 따라 크기 필드가 설정됩니다. 그런 다음 다른 함수에서 올바른 바이트 수를 전송하는 데 사용할 수 있습니다.
조합은 프로그램에 기계 독립적 정보를 포함시키지 않고 단일 스토리지 영역에서 다른 종류의 데이터를 조작하는 방법을 제공합니다. 파스칼의 변형 레코드와 유사합니다.
컴파일러 기호 테이블 관리자에서 볼 수있는 것과 같은 예로 상수가 정수, 부동 소수점 또는 문자 포인터 일 수 있다고 가정하십시오. 특정 상수의 값은 적절한 유형의 변수에 저장해야하지만 값이 동일한 양의 스토리지를 차지하고 유형에 관계없이 동일한 위치에 저장되는 경우 테이블 관리에 가장 편리합니다. 이는 여러 유형 중 하나를 합법적으로 보유 할 수있는 단일 변수 인 공용체의 목적입니다. 구문은 구조를 기반으로합니다.
union u_tag {
int ival;
float fval;
char *sval;
} u;
변수 u는 세 가지 유형 중 가장 큰 것을 보유 할 수있을 정도로 커질 것입니다. 특정 크기는 구현에 따라 다릅니다. 사용법이 일관된 한 이러한 유형을 u에 할당 한 다음 표현식에 사용할 수 있습니다.
'programing tip' 카테고리의 다른 글
여러 파일 확장자 searchPattern for System.IO.Directory.GetFiles (0) | 2020.07.08 |
---|---|
XmlSerializer : 불필요한 xsi 및 xsd 네임 스페이스 제거 (0) | 2020.07.08 |
Java FileReader 인코딩 문제 (0) | 2020.07.08 |
Python Windows 패키지를 virtualenvs에 설치할 수 있습니까? (0) | 2020.07.08 |
Android Studio에서 debug.keystore는 어디에 있습니까? (0) | 2020.07.08 |