CPP 기초 불리언 및 문자와 문자열

불리언 (bool)

bool isAlive = true;
bool isDead = false;

cout << isAlive;        // 1 출력
cout << isDead;         // 0 출력

실체는 1바이트 정수. 어셈블리에는 boolean이 없다. 0이면 false, 나머지는 true.

단순히 1과 0의 표현보다 가독성이 매우 뛰어나므로 사용함.
if (hp > 0) 보다 if (isAlive)가 의도가 명확함.


부동소수점 (Floating Point)

기본 타입

float f = 3.14f;        // 4바이트, f 붙여야 float
double d = 3.14;        // 8바이트, 기본값

f를 붙이는 이유는? 리터럴 3.14는 기본적으로 double. float에 넣으면 암시적 변환 발생.

IEEE 754 표준

float (32비트):  [부호 1비트][지수 8비트][가수 23비트]
double (64비트): [부호 1비트][지수 11비트][가수 52비트]

floating point = 떠다니는 소수점 (안움직이는 부동아님 뜰 부임)

// 3.141592를 다음과 같이 저장:
// 0.3141592 × 10¹ (소수점 위치가 "떠다님")
// 314.1592 × 10⁻² (같은 값, 다른 표현)

정밀도 한계

float f = 0.1f + 0.2f;
cout << (f == 0.3f);    // false! (부동소수점 오차)

// 해결책: 오차 범위 내에서 비교
float epsilon = 0.00001f;
bool equal = abs(f - 0.3f) < epsilon;

문자 (char)

char ch = 'a';          // 작은따옴표
char ch2 = 97;          // ASCII 코드로 직접 대입 (결과는 같음)
char ch3 = 'a' + 1;     // 'b' (ASCII 연산)

char 타입은 1바이트 정수. ASCII 코드로 문자를 숫자로 매핑.

유니코드와 wchar_t

wchar_t wch = L'한';    // L 접두사, 2바이트

// 출력 방법
wcout.imbue(locale("kor"));
wcout << wch << endl;

인코딩 방식:

  • UTF-8: 영문 1바이트, 한글 3바이트 (웹 표준)
  • UTF-16: 대부분 문자 2바이트 (윈도우 내부), 아주 일부만 4바이트

Escape Sequence

char tab = '\t';        // 탭
char newline = '\n';    // 개행
char quote = '\'';      // 작은따옴표
char backslash = '\\';  // 백슬래시

새 프로젝트를 열면 있는 Hello World에도 \n 이 포함되어 있다.


문자열 (String)

C 스타일 문자열

char str[] = {'h', 'e', 'l', 'l', 'o', '\0'};  // 수동 null terminator
char str2[] = "hello";                          // 자동 null terminator

cout << str2;           // hello 출력

중요: \0 (null terminator)가 문자열의 끝을 알려줌. 없으면 쓰레기값까지 출력.

C++ string 클래스 (권장)

#include <string>

string name = "Huxlley";
string greeting = "Hello, " + name + "!";

cout << greeting.length();      // 문자열 길이
cout << greeting[0];           // 첫 번째 문자

C 스타일 vs C++ string:

// C 스타일 (메모리를 직접 할당해줘야하는 번거로움, 아래의 경우에도 95바이트 가량 낭비임)
char str1[100] = "Hello";
char str2[100] = "World"; 
strcat(str1, str2);            // 문자열 연결

// C++ 스타일 (자동으로 메모리를 관리해줌. 아래의 경우엔 5바이트 + 여유분 조금)
string str1 = "Hello";
string str2 = "World";
string result = str1 + str2;   // 연결

버퍼 오버플로우 위험

C 스타일: 버퍼 오버플로우 위험

char str1[10] = "Hello";
char str2[20] = "World!!!!!!!!!!";

strcat(str1, str2);            // 크래시! str1 크기 초과
// str1은 10바이트인데 결과는 20바이트 필요

실제 메모리 상황:

str1 메모리: [H][e][l][l][o][\0][?][?][?][?]
             0  1  2  3  4   5  6  7  8  9

strcat 후:   [H][e][l][l][o][W][o][r][l][d][!][!][!][!][!][!][\0]
             0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16
                                        ↑ 범위 초과! 다른 변수 메모리 침범

C++ string: 자동 확장

string str1 = "Hello";
string str2 = "World!!!!!!!!!!";

string result = str1 + str2;   // 안전! 필요한 만큼 자동 할당

실제로 쓸때

문자열 비교:

// C 스타일 (잘못된 방법)
char str1[] = "hello";
char str2[] = "hello";
if (str1 == str2)              // 주소 비교! 항상 false

// C++ 스타일 (올바른 방법)
string str1 = "hello";
string str2 = "hello";  
if (str1 == str2)              // 내용 비교, true

성능 고려사항:

// 문자열 연결이 많을 때
string result;
for (int i = 0; i < 1000; ++i) {
    result += "hello";         // 매번 메모리 재할당 (느림)
}

// 더 효율적인 방법
result.reserve(5000);          // 미리 메모리 할당


다양한 버그


버퍼 오버플로우 보안 취약

char username[20];
cout << "사용자명: ";
cin >> username;               // 20자 이상 입력하면 해킹 가능

// 해커가 100글자 입력 → 스택 메모리 오염 → 코드 실행 권한 탈취

메모리 누수

char* str = new char[1000];    // 동적 할당
strcpy(str, "Hello");
// delete[] str;               // 깜빡하면 메모리 릭

초기화 실수

char str[100];                 // 쓰레기값
strcat(str, "Hello");          // 쓰레기값 + "Hello" = 예측불가


극도의 성능 최적화가 필요한 경우 C 스타일을 쓸 수 있으나 거의 대부분 상황에선 C++ String을 쓰는게 맞다.