[C++ 기초] 인코딩, String, 메모리 단편화, Release와 Debug차이, x64와 x86차이, WinApi 시작

라멘커비·2024년 1월 19일
0

CPP 입문

목록 보기
25/25

C++ 문법 모시깽

🍔자잘한 모시깽들..

  • static 멤버함수는 객체 없이 호출 가능
    static 멤버함수 안에는 this가 없다. 그래서 일반적인 멤버변수를 사용할 수 없다.

  • zero division

int Value = 1 / 0;	// zero division 에러
Value = 1 % 0;		// zero division 에러

int zero = 0;
int a = 1 / zero;	// zero division 에러
  • null reference exception
class Test {
public:
	int Value;
	void Function() {
		this->Value = 20;	// this가 null이기 때문에 null reference exception 발생
	}
};
Test* CreateTest() {
	return nullptr;
}

int main() {
	Test* NewTest = CreateTest();

	NewTest->Function();
	return 0;
}

어디가서 질문할 때 "왜 터지는지 모르겠다"가 아니라 "왜 this가 null인지 모르겠다"라고 질문해야 한다.

  • 조사식 기능 활용해서 값 확인 가능
    조사식에서 알고싶은 값 검색. 함수의 값도 알 수 있다.

🍔String

인코딩 방식

char는 unsigned기준 0~255 범위 => 256개밖에 표현 못함.
한글 100% 표현 불가능

숫자 1개와 문자 1개를 매칭시키는 방법을 인코딩이라고 한다. 인코딩에는 방식이 많을 수밖에 없다. 문자를 표현하기 위한 바이트 크기들이 다르기 때문이다.

  • 아스키 인코딩
    문자를 7비트로 표현. 초기형 인코딩 방식.
    아스키 인코딩 방식은 ansi 멀티바이트 방식이라고 불리는 방식에 통합된 방식이다. 한글을 고려할 필요가 없었다. 코딩에 필요한 문자가 256개에 매칭이 가능했다.

  • Ansi
    아스키의 확장형 문자열 방식. 문자를 1바이트로.

  • MultiByte
    어떤때는 1바이트 어떤 때는 2바이트로 표현하는 멀티바이트 방식이 만들어졌다. 65536개까지 가능해졌다. 한 나라의 문자는 모두 넣을 수 있어도 전세계의 문자를 넣을 수는 없었다. 국가코드라는 게 생겼다. 운영체제가 국가코드라는 것을 정함. 한국어 표현 가능해짐.

  • 유니코드 == WideByte
    그냥 다 2바이트로 하면 되는거 아니야? => 유니코드 혹은 와이드바이트 스트링이라고 불리는 방식이 만들어졌다.
    문자를 2바이트로 표현. 전용 자료형인 wchar_t를 c++에서 지원해준다.
    표현식 : L""

  • UTF-8
    문자를 1~4바이트로 표현. 전세계 모든 글자를 표현할 수 있다.
    이모지부터 여러 문자의 형태까지.. 이게 UTF-8, UTF-16 시리즈들.

아무것도 안 붙이고 문자 사용하면 멀티바이트 방식으로 사용된다. L을 붙이고 사용하면 유니코드방식으로 사용하겠다는 의미가 된다. UTF-8은 u8문자열 방식으로 지원한다.

선생님은 멀티바이트를 기본으로 사용하고 필요시에 와이드 바이트나 UTF-8로 변환하여 사용할 예정. 그냥 char Arr[100] 쓴다는 뜻.

함수 사용하다보면 문자열 넣어야 할 때가 있다. 그런데 동작하지 않으면 내가 넣은 문자열의 값이 잘못된 것이 아니고 문자열 인코딩이 잘못되서 그럴 수 있다는 걸 생각할 수 있어야 한다.

String 클래스

string은 벡터라고 생각하면 편하다. reserve도 있고 capacity도 있고..

문자열 더하기 쉽다.

	std::string Text0;
	Text0.reserve(3);
	Text0 = "가";
	
	std::string Text1;
	Text1.reserve(3);
	Text1 = "나";

	std::string Text2 = Text0 + Text1;		// "가나"

🍔메모리 단편화

동적할당을 많이 하다보면 램의 메모리에 데이터 사이 틈새 공간이 생긴다.

메모리를 할당한다 => 느려진다.
메모리를 할당하기 위해 빈 공간을 찾는다 => 느려진다.
메모리를 삭제한다 => 느려진다.

String을 쓸 때 함수에 값형으로 인자를 넘기는 코드는 이득이 거의 없기 때문에 주의해야 한다.

🍔release debug 차이

debug 모드는 최적화가 안 되어 있는 코드를 보여준다. 디버그 모드일 때는 인간이 이해하기 쉬운 모드로 변환하고 이름을 다 기억해 놓는다. 함수, 변수 이름 등을 다 기억해 놓는다.

release 모드에서는 최적화를 모두 끝낸 상태로 보이기 때문에 변수 A가 A의 이름으로 있지 않는다. 눈에 보이는 모습이 아닌 컴퓨터가 가장 빠르다고 생각하는 모습으로 변경시킨다.
release 모드에서도 중단점을 걸 수는 있지만 의미가 없다(값을 볼 수가 없음). 모든 최적화가 다 끝난 상태이기 때문에 3~5배 이상의 프레임이 오른다. 출시는 release로 해야 한다.

빌드하고 값을 확인했는데 말도 안되는 이상한 값이면 릴리즈모드인지 의심할 줄 알아야 함.

커밋하기 전에 디버그모드와 릴리즈모드 둘 다 컴파일 돌려보고 커밋하는 것이 좋다.

모든 구성으로 해놓고 속성 고쳤던 이유.

🍔x64, x86 차이

x86은 32비트를 말하고 과거에 쓰였던 빌드 방식.
x86에서는 포인터가 4바이트이다.
램이 4기가가 안되는 컴퓨터들이 많았다.

x64는 64비트임. 포인터 8바이트.
이제는 4기가 이하 램을 쓰는 컴퓨터를 찾는 게 어렵다.

WinApi 시작

  • Api(Application programming interface)
    인터페이스 : 함수 클래스 멤버변수 멤버함수 등을 모조리 다 포함. 어떤 동작을 하는 코드를 사용하기 위한 모든 방법을 인터페이스라고 함.
    ex) 소리를 재생하기 위한 함수가 있음 =>
    "소리를 재생하기 위한 인터페이스를 제공했다, 소리를 재생하려면 xxx 클래스를 사용해야 한다.", "소리를 재생하려면 xxx클래스를 통한 인터페이스를 제공한다."
    xxx 클래스에 xxxx 함수가 있다. xxx 클래스에는 xxxx 인터페이스가 존재한다.

  • WinApi
    => Window를 사용하기 위한 모든 클래스 방법 함수 변수 머시기 등등을 다 종합해서 Win 어플리케이션 프로그래밍 인터페이스라고 부른다.

윈도우에서 앱을 만들기 위한 기본적인 방법을 담아둔 옵션

프로젝트 만들자마자 실행

하위 시스템이 창으로 돼있음. 이거 때문에 진입점이 wWinMain으로 바뀌어있음.
이전에 CPP는 콘솔로 돼있었음.

  • 코드
    hInstance : 내 프로그램의 제어권한이자 표식 (xx번 프로그램)
    hwnd : 윈도우 창을 제어할 수 있는 제어권한이자 표식 (xxx번 창)
// WindowsProject1.cpp : 애플리케이션에 대한 진입점을 정의합니다.
//

#include "framework.h"
#include "WindowsProject1.h"

#define MAX_LOADSTRING 100

// 전역 변수:
HINSTANCE hInst;                                // 현재 인스턴스입니다.
WCHAR szTitle[MAX_LOADSTRING];                  // 제목 표시줄 텍스트입니다.
WCHAR szWindowClass[MAX_LOADSTRING];            // 기본 창 클래스 이름입니다.

// 이 코드 모듈에 포함된 함수의 선언을 전달합니다:
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    // 경고 레벨이 높아지면 인자를 사용하지 않아도 경고가 난다. 억지 사용하는 코드.
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    // hInstance : program number

    // TODO: 여기에 코드를 입력합니다.

    // 전역 문자열을 초기화합니다.
    //LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    //LoadStringW(hInstance, IDC_WINDOWSPROJECT1, szWindowClass, MAX_LOADSTRING);

    swprintf_s(szTitle, L"title");
    swprintf_s(szWindowClass, L"tttt");

    // szWindowClass를 만드는곳?
    MyRegisterClass(hInstance);

    // 애플리케이션 초기화를 수행합니다:
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }

    HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WINDOWSPROJECT1));

    MSG msg;

    // 기본 메시지 루프입니다:
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int) msg.wParam;
}



//
//  함수: MyRegisterClass()
//
//  용도: 창 클래스를 등록합니다.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEXW wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINDOWSPROJECT1));
    wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName   = MAKEINTRESOURCEW(IDC_WINDOWSPROJECT1);    // nullptr넣으면 메뉴 안 뜸
    wcex.lpszClassName  = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    // RegisterClassExW 윈도우에게 알려준다.
    // WNDCLASSEXW wcex; 에 입력한 모양대로 띄워주라는 의미. 그리고 그 모양이 szWindowClass모양이라고 할게...
    return RegisterClassExW(&wcex);
}

//
//   함수: InitInstance(HINSTANCE, int)
//
//   용도: 인스턴스 핸들을 저장하고 주 창을 만듭니다.
//
//   주석:
//
//        이 함수를 통해 인스턴스 핸들을 전역 변수에 저장하고
//        주 프로그램 창을 만든 다음 표시합니다.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   // hInst 내 프로그램의 제어권한이자 표식
   hInst = hInstance; // 인스턴스 핸들을 전역 변수에 저장합니다.
   

   // HWND hWnd 윈도우를 제어할 수 있는 제어권한이자 표식
   HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);

   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);  // hWnd 윈도우를 띄워주라는 뜻
   UpdateWindow(hWnd);

   //ShowCursor(false); no cursor

   return TRUE;
}

//
//  함수: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  용도: 주 창의 메시지를 처리합니다.
//
//  WM_COMMAND  - 애플리케이션 메뉴를 처리합니다.
//  WM_PAINT    - 주 창을 그립니다.
//  WM_DESTROY  - 종료 메시지를 게시하고 반환합니다.
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_COMMAND:
        {
            int wmId = LOWORD(wParam);
            // 메뉴 선택을 구문 분석합니다:
            switch (wmId)
            {
            case IDM_ABOUT:
                DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                break;
            case IDM_EXIT:
                DestroyWindow(hWnd);
                break;
            default:
                return DefWindowProc(hWnd, message, wParam, lParam);
            }
        }
        break;
    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
            // TODO: 여기에 hdc를 사용하는 그리기 코드를 추가합니다...
            EndPaint(hWnd, &ps);
        }
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

// 정보 대화 상자의 메시지 처리기입니다. help tab 
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}
profile
일단 시작해보자

0개의 댓글

관련 채용 정보