-
Notifications
You must be signed in to change notification settings - Fork 0
[CPP] 제 2장 변수와 기본 타입
-
char : 1 byte 의 문자
-
wchar_t : 일본어, 중국어, 한국어 등 char의 1 byte 로 처리할 수 없는 문자. 2 bytes(extended character sets) -
C++ 컴파일러에서는 unsigned 타입에 대해서는 범위를 넘어서는 값이 들어오면 (예를 들어 unsigned int 의 경우 0 ~ 255), modulo 연산을 통해서 나머지를 반환한다. 예를 들어
unsigned char a = 333;
std::cout << (int)a << endl;
를 출력하면, unsigned char 가 표현할 수 있는 값이 0~255 이기 때문에 333%256 = 77 이 출력이 된다. 그리고 일부 언어들에서는 unsigned 에 음수값의 대입을 절대 허용하지 않지만, c++ 에서는 음수값도 입력을 받고, 그 값은 똑같이 modulo 연산을 한 값이 된다. 예를 들어,
unsigned char a = -1;
std::cout << (int)a << std::endl;
unsigned short(2byte) 로 선언했을 때, 65535 값이 나온다 char 타입 : 8bit / short 타입 : 16bit / int 타입 : 16bit / long 타입 : 16bit
- 어떤 상황에서 어떤 데이터 타입을 쓸까 고민이 될 때... (맨날 int, double 만 쓰잖아. 왜 그럴까.)
- counting 을 하는 상황일 떄는 unsigned 를 사용할 것 : count 를 하는데 음수 값이 나오는 것을 방지하기 위함.
- 정수형 산술연산을 할 때, short 은 사용하지 말 것. short 이 담을 수 있는 수 보다 큰 값이 들어왔을 때 큰 음수 값이 발생하게 되면서 많은 버그들을 불러 올 수 있다. char 도 비슷한 이유에서 사용하지 말 것.
- 일반적인 32 bit 컴퓨터에서 int 와 long 은 같은 32 bit 를 가지고, 64bit 컴퓨터에서는 int 는 32 bit, long 은 64 bit를 사용한다. 이 때, 어느 데이터 타입을 쓸까 고민한다면, long 이 int 보다 연산비용이 더 많이 든다.
- float 와 double 둘 중에 무엇을 쓸까 고민을 한다면, double 을 쓰는 것이 옳다. float 은 single precision 이고, double 은 double precision 인데, double precision 연산이 더 빠르다. https://stackoverflow.com/questions/801117/whats-the-difference-between-a-single-precision-and-double-precision-floating-p
- 가끔 정수에 붙어있는 L, U, l, u 는 각각 long 과 unsigned 로 강제로 정의하기 위해서 사용이 된다. ex) 1L, 20UL
- 실수는 기본이 double 인데, f, F 를 통해서 float 로 지정해줄 수 있고, e, E 를 통해서 소수점 아래 자리를 정의할 수 있다. ex)
std::cout << 1E-5 << std::endl;
위 코드의 출력값은 1e-05 즉, 0.00001 이다.
- 'x' 는 기본적으로 char 타입을 지원하는데 wchar_t (extended character) 에 대한 값은 L'a' 로 지정할 수 있다.
- string 에 대해서도 똑같다. L"a" 로 wchar_t 타입을 지원할 수 있다.
⚠️ 내 xcode 에서는 돌아가는데, 원래 두 개의 다른 타입을 이어서 출력을 할 수 없다고 한다. 예를 들어
std::cout << "hello" << L"world" << std::endl;
근데 나는 출력은 잘 되는데, L"world" 가 world 를 출력하지 않고, 그 주소를 출력하는 것 같다. 0x100000f90.
이유를 알았다. 여기 에 따르면, cout 이 아니라 wcout 을 사용해야한다고 한다. 그렇게 바꾸니까 올바른 값이 출력되었다. 하지만 그래도 다른 타입을 이어붙여서 출력하는 것은 좋은 습관은 아니다. 작동하는게 내 작업환경에서만 작동하는 것일 수 있기 때문에.
미션 : wchar_t 에 대한 string 을 하나 만들고, wcout 으로 출력하기 (warning : C++11 이 string to wchar_t 로의 변환을 지원하지 않는다)
- 변수 값의 초기화
⚠️ C++ 에서 초기화와 대입을 헷갈리면 안된다. 초기화도 = 연산자를 쓰고, 대입도 = 연산자를 쓰는데 뭐가 다르다는거야? 라고 하지만, 엄연히 다른 연산자라고 한다.
13장에서 다룰 내용인데 미리 다뤄본다 (이렇게 구분을 해놓은 이유가 있겠지. 클래스의 객체를 초기화할 때 약간 다른 의미를 가질 수 있다. 이 차이는 low level optimization 단계에서 필요하다.
- direct-initialization : 바로 생성자를 invoke 를 한다. 바로 생성자를 호출하여 생성한 객체에 값을 넣는다.
int num (10);
- copy-initialization : 생성자의 복사본을 갖는다?(copy)
int num = 10;
임시 생성자를 호출하여 값을 넣고, 그 값을 내가 만든 객체 변수에 복사한다. 여기서 copy-initialization 은 여러가지 제약이 있는 것을 알 수 있다. 첫 번째로, copy 를 허용하지 않는 클래스의 경우 copy-initialization 을 할 수 없다. (예를 들어, file object 의 경우 copy 를 허용하지 않는다) 두 번째로, copy 에 대한 비용이 든다는 것이다. 컴파일러에서 처음에 임시 객체를 하나 생성한 다음에, 임시 객체에 있는 값을 할당해주는 방식이므로 비용이 더 든다. 예를 들어,
string str1 ("some strings");
string str2 = "some string";
는 작동하는 방식이 완전히 다르다. str1 의 경우 바로 클래스 string 의 "C 형식의 string" 을 파라미터로 받는 생성자를 호출해서 "some string"을 할당하고, str2에서는 "some string" 이라는 값을 가지는 임시 생성자를 생성한 다음 그 값은 strcpy 로 복사를 하는 작업을 한 번 더 하게 된다. (좀 더 자세한 내용은 제 13장에서 다룬다고 한다)