본문 바로가기
개인공부/Rookiss C++ 프로그래밍 입문

Chapter 2 - 데이터 갖고 놀기

by 하고싶은건많은놈 2023. 3. 29.

정수

변수 선언은 [타입] [이름]; 혹은 [타입] [이름] = [초기값];으로 함
함수 외부에 변수 선언시 0이 아닌 초기화 값이 있으면 data영역, 초기값이 0이거나 없다면 bss영역에 저장됨

  • char : 1바이트, short : 2바이트, int : 4바이트, long long(__int64) : 8바이트
  • 기본적으로는 signed가 생략되어있으며, unsigned로 설정시 최상위비트를 항상 1로 고정하여 양수만 나타냄
  • 이론적으로 양수만 존재할 수 있는 데이터의 경우 unsigned를 선택할지 말지의 여부는 스타일에 따라 다를 수 있음
  • 필요 메모리에 따라 데이터형의 크기를 잘 선택해야함
  • 데이터형의 범위를 넘어갈경우 오버플로우와 언더플로우가 발생할 수 있으므로 유의

불리언과 부동소수점

불리언(boolean) : 참(true) 또는 거짓(false)만을 나타내는 자료형

  • 사실은 1바이트 정수에 불과함
  • 단, bool이라는 키워드 만으로도 참/거짓 둘중 하나라는 것을 알 수 있기 때문에 가독성이 뛰어남

실수(부동소수점) : float, double형이 있음

  • 실수는 기본적으로 double형으로 지정
  • 유효숫자와 지수를 사용한 정규화로 표현
  • float : 4바이트, 부호(1비트) + 지수(8비트) + 유효숫자(23비트)
  • double : 8바이트, 부호(1비트) + 지수(11비트) + 유효숫자(52비트)

-3.375를 저장할 경우

  • 2진수로 변환 : 3.375 = 3 + 0.375 = 0b11 + 0b0.011
    • 3 = 2 * 1 + 1 * 1 -> 0b11
    • 0.375 = 0.5 * 0 + 0.25 * 1 + 0.125 * 1 -> 0b0.011
  • 정규화 : 0b1.1011 * 2^1
    • 1(부호), 1(지수), 1011(유효숫자)
    • 단, 지수는 unsigned byte라고 가정하고 숫자 + 127로 만들어줌
  • 결과 : 0b 1(1) 10000000(8) 1011000'0000'0000'0000'0000(23)

프로그래밍시 부동소수점은 항상 근삿값임
특히 수가 커질수록 오차 범위가 매우 커지며, 실수 2개를 ==으로 비교하는 것은 지양해야함


문자와 문자열

char : 정수형 1바이트지만 문자의 의미를 나타내기 위해 사용

  • ASCII 코드를 사용함
  • 문자의 의미로 작은따옴표 '' 사용

wchar_t : 유니코드 문자를 나타냄

  • 유니코드(unicode) : 전 세계 모든 문자에 대해 유일 코드를 부여한 것
  • 유니코드는 표기 방식에 따라 종류가 여러가지가 있으며, 대표적으로 UTF8, UTF16이 있음
    • UTF8 : 알파벳과 숫자는 1바이트, 유럽 지역 문자는 2바이트, 한글 / 한자 등은 3바이트
    • UTF16 : 거의 대부분의 문자가 2바이트, 매우 예외적인 문자만 4바이트
  • 유니코드 문자를 지정할때는 L'안'과 같이 앞에 L을 붙인 형식을 사용함
  • 단, 출력하기 위해서는 wcout.imbue(locale("kor")); 설정 후 wcout을 사용해야함

Escape Sequence : 표기하기 애매한 것들을 표현

  • \t, \n
  • '등의 문자를 사용하고 싶을 때도 사용함

문자열 : 문자들이 열을 지어서 모여있는 것

  • 문자열의 끝은 NULL = \0으로 인식함
  • 일반적으로는 ""를 사용하여 만들며, 이 경우 마지막에 NULL값이 자동으로 붙음

산술 연산

산술 연산 : 사칙연산, 대입연산 등

  • 대입 : a = b;, a에 b를 대입하고 b를 반환 - b의 값을 a에 복사
    값을 반환하기 때문에 a = b = 3;같은 형식으로도 사용 가능함
  • 사칙연산 : 덧셈 +, 뺄셈 -, 곱셈 *, 나눗셈 /, 나머지 %
    • a = b + 3, a += 3 등의 형태로 사용
    • 증감 연산자 ++, --를 변수의 앞 또는 뒤에 붙여 사용할 수 있으며, 순서에 유의해야함
    • a += 3a = a + 3은 효율에 차이가 없음

#pragma region#pragma endregion으로 특정 영역을 감출 수 있음


비교 연산과 논리 연산

비교 연산

  • a == b : a와 b의 값이 같으면 1, 다르면 0을 리턴
  • a != b : a와 b의 값이 같으면 0, 다르면 1을 리턴
  • a > b : a가 b보다 크면 1, 아니면 0을 리턴
  • a >= b : a가 b보다 크거나 같으면 1, 아니면 0을 리턴
  • a < b : a가 b보다 작으면 1, 아니면 0을 리턴
  • a <= b : a가 b보다 작거나 같으면 1, 아니면 0을 리턴

어셈블리어로 뜯어보면 비교 연산의 값을 스택에 임시로 저장한 뒤, 그 값을 레지스터에 저장한 후에 변수로 넣는 것을 확인할 수 있음

논리 연산

  • ! : not을 의미, 1이면 0, 0이면 1을 리턴
  • && : and를 의미, 둘 다 1이면 1, 그 외엔 0을 리턴
    앞 조건이 1이 아닌경우 곧바로 0을 리턴함
  • || : or를 의미, 둘 중 하나라도 1이면 1, 둘다 0이면 0을 리턴

비트 연산과 비트 플래그

비트 단위의 조작이 필요할 때가 종종 있음
대표적으로 BitFlag가 사용됨

  • ~ : bitwise not, 단일 숫자의 모든 비트를 대상으로 0은 1, 1은 0으로 뒤바꿈
  • & : bitwise and, 두 숫자의 모든 비트 쌍을 대상으로 and 연산을 수행
  • | : bitwise or, 두 숫자의 모든 비트 쌍을 대상으로 or 연산을 수행
  • ^ : bitwise xor, 두 숫자의 모든 비트 쌍을 대상으로 xor 연산(두 비트가 다르면 1, 같으면 0)을 수행
  • << : 비트 좌측 이동, 비트열을 n만큼 왼쪽으로 이동
    • 좌측으로 이동하여 범위를 벗어난 비트는 소멸되고, 우측에 새로 생성된 비트들은 0으로 설정됨
    • 곱하기 2 연산을 할 때 자주 사용됨
  • >> : 비트 우측 이동, 비트열을 n만큼 오른쪽으로 이동
    • 우측으로 이동하여 범위를 벗어난 비트는 소멸되고, 좌측에 새로 생성된 비트들은 부호에 따라 달라짐
    • 부호 비트가 존재할 경우 부호 비트를 따라가고, 아니면 0으로 설정됨
    • 따라서 비트 단위의 연산에는 unsigned 형이 유용하게 쓰임
const int INVINCIBLE = 2;
flag = (1 << 3); // flag = 0b1000, 8
flag |= (1 << INVINCIBLE); // flag = 0b1100

비트플래그는 다수의 boolean을 선언해야하는 상황에서 쓰일 수 있음
각 비트마다 상태를 지정하여 사용

bool invincible = ((flag & (1 << 3)) != 0);
bool stunOrinvincible = ((flag & 0b1010) != 0); // (1 << 3) | (1 << 1)과 같은 의미 

비트마스크(bitmask)로 각 비트의 상태를 확인


const와 메모리 구조

상수 : 한번 정해지면 절대 바뀌지 않을 값

  • constant의 약자인 const를 붙여서 변수를 상수화함
  • const 지정시 반드시 초기값을 설정해야함
  • 상수는 일반적으로 모두 대문자로 표기함

메모리 영역은 stack / heap / data / text 로 나뉘어짐

  • 전역 변수는 데이터 영역에 저장됨
    • 초기값이 있는 경우에는 .data, 없는 경우에는 .bss 영역에 저장됨
    • const char * msg = "Hello World"의 에서의 msg의 경우 .rodata(읽기 전용 데이터) 영역에 저장됨
  • 지역 변수는 스택 영역에 저장됨
  • 상수는 어느 영역에 저장하라는 C++ 표준이 존재하지 않음

유의사항

변수의 유효범위 : 스택에 할당되는 변수의 경우 중괄호의 범위가 생존 범위
같은 이름의 변수를 두번 사용할 때 문제가 발생함

연산 우선순위 : 우선순위가 확실하지 않은 경우는 괄호를 활용할 것

타입 변환

  • 자신보다 작은 크기의 자료형으로 변환할시 데이터의 손실이 발생함
  • 정수를 실수로 변환할시 정밀도 차이로 인한 데이터 손실이 발생
  • unsinged 형으로 변환할 시에도 비트 단위로 보면 같은 수이나 분석하는 방법이 달라지기 때문에 주의가 필요

곱셈의 경우 오버플로우를 주의
나눗셈의 경우 0으로 나누는 경우와 실수 형식을 주의

'개인공부 > Rookiss C++ 프로그래밍 입문' 카테고리의 다른 글

Chapter 6 - 객체지향 여행  (0) 2023.03.29
Chapter 5 - 포인터  (0) 2023.03.29
Chapter 4 - 함수  (0) 2023.03.29
Chapter 3 - 코드의 흐름 제어  (0) 2023.03.29
Chapter 1 - 어셈블리 언어 입문  (0) 2023.03.29

댓글