// 13-1 : 공용체의 특징 확인
#include <iostream>
using namespace std;
union MyUnion
{
int i;
void* p;
};
int main()
{
MyUnion uni;
// 멤버의 주소확인
cout << &uni.i << "\n";
cout << &uni.p << "\n";
// i에 값을 대입하는 것이 p에도 영향을 미친다.
uni.i = 0x12345678;
cout << hex;
cout << uni.i << "\n";
cout << uni.p << "\n";
// p에 값을 대입하는 것이 i에도 영향을 미친다.
uni.p = (void*)0x87654321; // 실제 코드 작성시 절대 이렇게 하지 말라. 실험을 위해 상수를 주소값인것처럼 형변환하여 넣었다.
cout << uni.i << "\n";
cout << uni.p << "\n";
return 0;
}
/*
--- 결과 ---
0000001A8E8FF688
0000001A8E8FF688
12345678
CCCCCCCC12345678
87654321
0000000087654321
---
// 공용체의 기본
공용체는 사용 빈도가 높지 않다.
구조체와 비슷하게 생겼지만 모든 멤버가 같은 메모리 공간에 자리잡는다.
uni.i주소와 uni.p의 주소가 동일하다.
i에 값을 넣어주면 p도 변한다.
// 공용체의 특징
어느 한쪽의 멤버값 변경이 다른 멤버 값에 영향을 미친다.
3개 이상인 경우도 마찬가지로 모든 멤버가 같은 메모리 공간을 사용한다.
타입마다 크기가 다른 경우는?
공용체 변수의 크기는 가장 큰 크기를 갖는 멤버의 크기와 같다. (제일 큰 것 사용)
*/
// 13-2 : 열거체의 사용 1
enum {JOB_DWARF, JOB_WARRIOR, JOB_SORCERER}; // 0, 1, 2를 의미한다.
struct Character
{
int jobType;
// 다른 멤버들이 더 있다.
};
int main()
{
Character c;
// c가 누군가에 의해 초기화 된다.
if (JOB_SORCERER == c.jobType)
{
// 코드 작동
}
return 0;
}
/*
--- 결과 ---
---
주석이 없더라도 마법사라는 것을 쉽게 알 수 있다.
// 해석
첫번째 줄은 다음과 동일하다.
enum {JOB_DWARF = 0, JOB_WARRIOR = 1, JOB_SORCERER = 2};
차례대로 0,1,2...가 된다.
// 주의사항
사용자에 의해 초기화 되면 그 이후 심볼들은 그 값을 기반으로 다시 증가한다.
enum {JOB_DWARF, JOB_WARRIOR = 3, JOB_SORCERER}; 와 같이 쓰면,
enum {JOB_DWARF, JOB_WARRIOR = 3, JOB_SORCERER = 4}; 과 동일하다.
*/
// 13-3 : 열거체의 사용 2
enum JOB_KINDS { JOB_DWARF, JOB_WARRIOR, JOB_SORCERER }; // 열거체가 JOB_KINDS라는 하나의 타입이 된다.
struct Character
{
JOB_KINDS jobType;
// 다른 멤버들이 더 있다.
};
int main()
{
Character c;
// c가 누군가에 의해 초기화 된다.
if (JOB_SORCERER == c.jobType)
{
// 코드 작동
}
return 0;
}
/*
--- 결과 ---
---
JOB_KINDS 타입은 새로운 정수형 타입이 된다.
열거체는 기본적으론 정수형 타입이다.
하지만 다른점도 많다.
- 덧셈과 같은 연산 수행이 불가하다.
- 정수를 열거체 변수에 대입하는 것 불가하다. (반대는 가능하다)
Color = color2;
color2 = 5; // 오류
열거체 변수에 저장하는 값은 결국 숫자다.
숫자를 해석하는 방식의 차이일 뿐이다.
// 열거자
열거체 안의 하나하나의 심볼을 열거자(Enumerator) 혹은 나열자라고 한다.
*/
// 13-4 : 레퍼런스의 기본적인 사용
#include <iostream>
using namespace std;
int main()
{
int target = 20;
int& ref = target; // 레퍼런스 변수 정의
cout << ref << "\n";
cout << target << "\n";
cout << &ref << "\n";
cout << &target << "\n";
// ref 값 변경
ref = 100;
cout << ref << "\n";
cout << target << "\n";
return 0;
}
/*
--- 결과 ---
20
20
00000068518FF994
00000068518FF994
100
100
---
// 레퍼런스와 const
레퍼런스는 반드시 초기화해야한다.
처음에 a를 참조하게 지정했다면 죽을때까지 a를 참조한다.
const 속성을 가진 레퍼런스는 추가적 특징을 가진다.
상수에 대한 별명으로 쓰일 수 있다.
const int& rci = 100; // 성공
int& ri = 100; // 실패. const가 아니라서 안된다.
레퍼런스 변수는 상수 바로 참조는 불가하다.
따라서 임시 변수(객체)를 만든 후 레퍼런스가 이 임시 변수를 참조하게 만든다.
const 속성을 가진 레퍼런스는 다른 타입의 변수 참조를 할 수 있다.
char c = 'A';
const int& rci = c;
// typedef
타입에 대한 별명을 만드는데 사용한다.
1. 긴 타입 이름을 짧게 줄여쓴다.
2. 의미를 보다 분명하게 해준다.
/ 사용예시
typedef unsigned char* uc_ptr;
이제 uc_ptr이라고 쓰면 된다.
uc_ptr p = &uc;
// typedef 다른 용도
타입이 바뀔 수 있는 대비용으로 사용 가능하다.
typedef short ID_TYPE
ID_TYPE id1 = (ID_TYPE)0;
ID_TYPE id2 = (ID_TYPE)0;
나중에 아이디 저장하는 변수 타입이 int로 변경될 경우를 위한 준비다.
short로 담을 수 있는 수보다 더 많은 아이디가 필요할 때 int로 바꾸기 위함이다.
*/
// 13-5 : 16비트 칼라의 한 점에서 파란색만 추출
#include <bitset>
#include <iostream>
using namespace std;
// 16비트 칼라에서 한 점을 나타내는 구조체
struct Pixel16
{
// R G B가 각각 5 6 5 를 차지한다.
unsigned int blue : 5;
unsigned int green : 6;
unsigned int red : 5;
};
// unsigned short 타입 값을 Pixel16 구조체로 변환하기 위한 용도다.
union Convert16
{
Pixel16 pixel;
unsigned short us;
};
int main()
{
// 한점의 색상을 보관하는 변수. 임의의 색상 넣었다.
unsigned short color = 0x1234;
// Pixel16 구조체 타입인것처럼 다루기 위해 공용체 사용한다.
Convert16 convert;
convert.us = color; // 색상 정보 대입한다.
// 출력
cout << bitset<16>(color) << "(" << color << ")" << "\n";
cout << bitset<16>(convert.pixel.blue) << "(" << convert.pixel.blue << ")" << "\n";
return 0;
}
/*
--- 결과 ---
0001001000110100(4660)
0000000000010100(20)
---
비트필드를 사용하면 구조체의 멤버 메모리 공간 조절할 수 있다.
멤버 a는 3비트만, 멤버 b는 4비트만 차지하게 가능하다.
int a : 3;
int b : 4;
비트필드를 사용하는 멤버는 정수 타입만 가능하다.
사용하지 않는 비트를 넣고 싶을 때는, 멤버의 이름을 적어주지 않으면 된다.
int : 5;
비트 필드는 비트 단위의 논리 연산을 대신해 사용할 수 있다.
// 예제 설명
파란색 값만 추출해내는 예제이다.
// 공용체 형변환
스킵하였다. 아직 이해가 가지 않는다.
// 비트필드 효율적인가?
비트 단위 논리 연산자보다 빠르진 않다.
데이터는 더 적은 메모리를 차지하지만,
코드는 더 많은 메모리를 차지한다.
// 구조체를 포함하는 구조체 등...
여러가지 내용이 책에 있으나 많아서 우선 스킵하였다.
*/
'C++ > 뇌를 자극하는 C++' 카테고리의 다른 글
[C++] 챕터 15 - 함수 2 : 함수의 모든 것 (0) | 2023.06.14 |
---|---|
[C++] 챕터 14 - 함수 1 : 관련된 코드 모아담는 가방 (0) | 2023.06.14 |
[C++] 챕터 12 - 배열과 구조체와 포인터 : 복합적인 방법으로 정보를 다루는 법 (0) | 2023.06.14 |
[C++] 챕터 11 - 포인터 : 정보에 대한 정보 (0) | 2023.04.27 |
[C++] 챕터 10 - 구조체 : 다양한 타입의 정보를 한 곳에 모으는 법 (0) | 2023.04.27 |
댓글