[UE5 TIL] Day 7 - C/C++ 강의 수강

JungHoon Eum·2026년 3월 4일

오늘 배운 내용 요약

  • C/C++ 코드가 실행 파일이 되기까지의 전체 빌드 과정을 다시 정리했다.
  • 솔루션 / 프로젝트 / 소스코드의 관계를 감 잡았다.
  • 네이밍 규칙(PascalCase, camelCase, snake_case)과 출력 관련 기초 문법을 복습했다.
  • 자료형, 선언과 초기화, 리터럴, 값/식/문, 형변환 개념을 다시 정리.
  • 배열을 이용해 여러 데이터를 묶어서 관리하고, 반복문으로 처리하는 방법을 연습.
  • 함수를 만들 때 인자 / 동작 / 반환이라는 구조 이해.
  • 값 전달, 주소 전달, 레퍼런스 전달의 차이를 배웠다.
  • 조건문과 반복문을 사용해 계산기와 다이아몬드 별 출력 코드를 작성했다.
  • 포인터의 기본 개념, 역참조, 배열과의 관계를 정리했다.
  • 배열과 포인터의 차이, 포인터 배열과 배열 포인터, 레퍼런스와 상수 레퍼런스까지 학습.

키워드

C

  • 천천히 읽기
  • 솔루션/프로젝트/소스 코드
  • 이스케이프 시퀀스
  • 서식 지정자
  • 네이밍 규칙 (카멜케이스, 스네이크 케이스, 파스칼 케이스)
  • 리터럴/자료형
  • 값/식/문

C++

  • 조건문, 반복문
  • 배열, 포인터, 레퍼런스

C언어 재강의 내용

  • 소스 코드(.h, .c)->전처리기->확장된소스코드(.pre)->컴파일러->어셈블리코드(.s)->어셈블러->오브젝트 코드(.o) -> 링커 -> 머신 코드(.exe) 실행 파일 까지

우리는 소스 코드 작성법 배우는.

  • 솔루션-프로젝트-소스 코드: 솔루션은 제품 그 자체. 솔루션(오감자) 프로젝트(봉투, 과자, 디핑소스), 소스코드 (실제로 각 프로젝트 동작하게 만드는)

  • 파스칼 케이스: EatDoNotDrink 카멜케이스: eatDoNotDrink 스네이크 케이스: eat_do_not_drink

  • \n, \t - 개행, 탭. 따옴표/쌍따옴표/역슬래시는 \ 추가로. %% 이 %출력

  • %d -> 10진수 표시. %c, %f, %s 등등 서식 지정자 중요.

  • 리터럴 - 소스코드에 적힌 값 그 자체.

- 자료형 -

자료형크기 == 표현 가능한 수서식 지정자
char1 byte. -(2^7) ~ (2^7) - 1
[-128 ~ 127]
%c or %hhd
short int2 byte. -(2^15) ~ (2^15) - 1
[-32768 ~ 32767]
%hd
int
[기본 정수 자료형]
4 byte. -(2^31) ~ (2^31) - 1
[-2147483648 ~ 2147483647]
%d or %i
long4 byte or 8 byte%ld
long long8 byte. -(2^63) ~ (2^63) - 1%lld
float4 byte. 유효 자릿수 6~7자리.
[부호: 1bit, 지수: 8bit, 가수: 23bit]
%f
double
[기본 실수 자료형]
8 byte. 유효 자릿수 15~16자리.
[부호: 1bit, 지수: 11bit, 가수: 52bit]
%lf
long double8 byte 이상%Lf
  • 선언과 초기화: 선언은 그냥 이 변수가 "있다." 초기화는 값까지 줌. C언어에선 기본값 그냥 0 따위로 안준다. 초기화안하면 이상하게 작동함
  • ASCII 기준 48: 0, 65: A, 97: a

-값, 식, 문: 값은 리터럴. 식은 피연산자+연산자로 이루어진 값, 문은 수행할 명령어 like if()

  • 형변환 연산자(TypeCast) ->
5 / 2; // == 2로 나온다
(float)5 / 2; // == 5.0f / 2 == 2.5f
  • 천천히 읽기 예시
    1. integer i 선언.
    2. for문에서 초기값으로 i에 1 대입.
    3. i<5는 1이므로 참.
    4. i를 10진수로 출력하고 뒤에 공백 추가.
    5. for 문 끝났으므로 ++i로 1 추가. i=2.
    6. i<5는 2이므로 참.
    7. i를 10진수로 출력하고 뒤에 공백 추가.
    8. for 문 끝났으므로 ++i로 1 추가. i=3.
    9. i<5는 3이므로 참.
    10. i를 10진수로 출력하고 뒤에 공백 추가.
    11. for 문 끝났으므로 ++i로 1 추가. i=4.
    12. i<5는 4이므로 참.
    13. i를 10진수로 출력하고 뒤에 공백 추가.
    14. for 문 끝났으므로 ++i로 1 추가. i=5.
    15. i<5는 5이므로 거짓. for 문 끝. return 0; 로 0 반환하고 main 함수 끝.

게임 개발자를 위한 C++ 문법

1-2. 프로그래밍 기초(2)

배열

  • 만 명의 학생의 점수 관리하는 프로그램 -> 각각 변수를 따로 선언하고 하지 않는 이유는?

    • 매번매번 변수선언하고 입력, 출력하기 귀찮아진다.
    • 동일한 목적을 가지고 있는 변수들은 같이 관리해 주는 게 편해진다. 귤은 귤박스에 사과는 사과박스에!
  • 이 경우 사용하는 게 배열: 여러 데이터를 하나의 묶음으로. 반복문으로 데이터 처리를 효율적으로.

  • 성적관리 프로그램 목표: 입력받은 성적 저장. 합 구하기. 평균 구하기.

  • 배열 특징

    • 임의접근 가능: []를 통해서
    • 선언과 동시에 초기화 및 선언 후 추후 초기화 가능
    • 통째 복사 및 대입 안됨. 반복문 써야 함
  • 성적처리 기기 코드 (학생5명 성적입력->평균 출력)

#include <iostream>
using namespace std;


int main()
{
	int score[5];
	int sum = 0;
	float average = 0.0f;
	int i;
	for (i = 0; i < 5; i++)
	{
		cout << "Score of Student " << i+1 <<" "<< "is: " << endl;
		cin >> score[i];
	}
	for (i = 0; i < 5; i++)
	{
		sum += score[i];
	}
	average = (float)sum / 5;

	cout << "Average Score is " << average << endl;
	return 0;
}

함수

  • 함수: 반복적으로 사용하는 코드, 논리적으로 묶이는 코드 하나로 이름붙여 갖다쓰기.

  • 작업 정의하기: 숫자 두개 가져와서 더한 값 반환하는 작업(함수) 생각해 보자

    • 인자: 작업에 사용되는 외부 값. Num1 Num2
    • 동작: 어떤 동작을 수행할 지. 중괄호 안의 다양한 내용들
    • 반환: 어떤 값을 반환할 지. return " "; 이런 식으로. 반환 안하고 반환타입 void 일 수도!

#include <iostream>
using namespace std;

// 숫자(integer) 두 개 더해주는 함수
int add(int a, int b) { // 여기에 "인자" 2개 a b 들어옴
    return a + b; // 결과 반환: 함수 타입 int임에 주목
}

int main() {
    int result = add(3, 7);
    cout << "3 + 7 = " << result << endl; // 출력: 3 + 7 = 10
    return 0;
} 
  • 값 전달법
    • 일반 변수 (int a, int b...): 값 전달
      • 그 값을 복사해서 가져와서 쓰고 사라짐. 원래 값은 변하지 않음
    • 주소값 전달 (int* a, &Num 같이)
      • 원본 주소에 있는 값도 바뀔 수 있다.
    • 주소값 전달할 때 &Num 자체를 넘길 수도, Num을 넘기고 void getaddress(int& X){ } 같이도 가능
    • 참조자(레퍼런스) 와 포인터(*) 는 다르다! 레퍼런스는 기존 문법 고대로 사용 가능

프로그래밍 기초(3)

계산기에 사칙연산/ %0 금지 시키기!

조건문

  • if, else if, else: else엔 조건문 필요없다!
  • 가능하면 else if 활용하면서 조건문 깔끔하게 넣기
#include <iostream>

using namespace std;

int main()
{
	int Num1;
	int Num2;
	char Operator;
	cout << "First Number: " << endl;
	cin >> Num1;
	cout << "Enter Operator +, -, *, /: " << endl;
	cin >> Operator;
	cout << "Second Number: " << endl;
	cin >> Num2;


	if (Operator == '+')
	{
		cout << "Result is: " << Num1 << Operator << Num2 << " = " << Num1 + Num2 << endl;
	}
	else if (Operator == '-')
	{
		cout << "Result is: " << Num1 << Operator << Num2 << " = " << Num1 - Num2 << endl;
	}
	else if (Operator == '*')
	{
		cout << "Result is: " << Num1 << Operator << Num2 << " = " << Num1 * Num2 << endl;
	}
	else if (Operator == '/')
	{
		if (Num2 != 0)
		{
			cout << "Result is: " << Num1 << Operator << Num2 << " = " << Num1/Num2 << ". Remainder: " << Num1 % Num2 << endl;
		}
		else 
		{
			cout << "Cannot Divide by Zero!!" << endl;
		}
	}
	else
	{
		cout << "Invalid Operator" << endl;
	}
	return 0;
}
  • 복합 조건문: &&는 AND, ||는 OR

반복문

  • for(초기화; 종료 조건; 사후 동작) {동작} 형식
  • 입력받은값 기반으로 다이아몬드 스타 만들기
#include <iostream>

using namespace std;

int main()
{
	int num;
	int i;
	int j;
	cout << "Half Height For Your Diamond Star: " << endl;
	cin >> num;

	if (100 > num && num > 1)
	{
		for (i = 0; i < num; i++) //피라미드파트 열 = i-1
		{
			for (j = i; j < num; j++) //num-1개, num-2개...
			{
				cout << " ";
			}
			for (j = 0; j <= 2*(i); j++) // 1개, 3개, 5개...
			{
				cout << "*";
			}
			for (j = i; j < num; j++)
			{
				cout << " ";
			}
			cout << endl; // i가 1열, 2열...이니 열 끝날때마다 개행
		}
		for (i = num-2; i >= 0; i--) //
		{
			for (j = i; j < num; j++) //num-1개, num-2개...
			{
				cout << " ";
			}
			for (j = 0; j <= 2 * (i - 1); j++) // 1개, 3개, 5개...
			{
				cout << "*";
			}
			for (j = i; j < num; j++)
            {
				cout << " ";
			}
			cout << endl;
		}

	}
	else
	{
		cout << "Invalid Half Height";
	}

	return 0;
}
  • 코드 자첸 나쁘지 않은데 이제 보니 오른쪽 공백들 채워넣는 건 필요없었네?

  • 추가로, 터미널 기준 이쁜 다이아몬드를 만드려면 앞쪽 공백을 공백 2개, * 뒤에도 공백 한개 추가해주면 된다.

포인터와 레퍼런스

기존 쓰던 변수 = 값을 담는 변수

  • "같은 값" 을 쓰고 싶다고 할 때 복붙 하면 하나하나 값을 실제로 복사하고 옆으로 옮기는 것. 비용(메모리) 가 많이 든다.
    • 특히 배열 복붙은 동일 변수가 여러개라 심함
    • 변수의 주소를 가리켜서 동일한 데이터에 접근할 수 있게 하는 것 -> 포인터!

포인터

  • 값 전체를 복사하는 게 아니라, 변수의 시작 주소를 알려줌.
    주소값은 고유하기 때문에, 이를 알고 있다면 실제 변수의 위치에 접근할 수 있다
  • int* p = &num; 식이던지 int* p = arr; 도 가능
    • 배열의 이름은 배열의 시작주소를 가지고 있다!
  • 타입이 정해져 있으니 (int 같이) 사이즈도 알고 있다. ptr+1로 배열의 다음 변수값도 가져올 수 있다.
  • char 포인터 출력을 원하는 경우 void형 타입캐스팅(void*) 가 필요하다는 것을 잊지 말 것 cout<<(void*)ptr;
  • 역참조: int* ptr의 경우 *ptr <- ptr 포인터가 가리키는 값.
  • 포인터를 초기화 안하고 접근하려고 하면? << 오류 발생. 페이탈 크래쉬 가능성. 일반 변수보다 리스크가 크다.

배열 이름의 의미

  • 배열도 변수다: 시작 주소를 가지고 있고 값을 저장할 수 있는 변수
    • 배열 자체는 선언되면 "연속된 원소들로 이루어진 배열 객체" 를 만드는 거지만, 포인터식으로 * 로 불러오면 "주소" 를 가져옴.
  • 값을 여러 개 담을 수 있는 변수다? 정확히는 변수를 "묶어서" 관리한다.
  • 같은 사이즈의 변수 여러개가 메모리에 연속적으로 할당되기 때문에 임의 접근이 가능
    • arr[k] = *(arr+k)
  • 배열 이름 자체가 주소값을 담기 때문에,
    한번 선언된 후 그 시작 주소를 변경할 수 없다

배열과 포인터의 차이

  • 주소값을 담고 있으면, 배열도 곧 포인터가 아니냐? X
  • 배열 이름에 담긴 주소값은 다른 주소값으로 변경 불가능
    • arr = &Y; 이딴 식 불가능
  • 변수의 크기 차이 -> 포인터는 어차피 '주소값' 이라 타입과 별개로 크기가 정해져 있다.
    • 배열의 크기는 원소 타입의 크기 * 갯수
  • 포인터 배열: 포인터를 원소로 갖는 배열
    • int* ptrArr[4] 는 크기가 4, 각 원소가 int* 인 배열
    • Right-Left Rule: ptrArr는 4개짜리 배열.
      배열의 내용물은 int에 대한 포인터
  • 배열 포인터: 배열 전체를 가리키는 포인터
    • int (*ptr)[4] = &arr; 이렇게 배열 전체의 주소 가져옴
    • 여기서도 Right-Left Rule: 포인터는 4개짜리 배열을 가르키는 포인터.
      int 변수를 가지는 배열

레퍼런스

  • 포인터는 주소값을 직접 다루어야 하므로 문법도 달라지고 복잡해짐
  • C++에서 일반 변수와 거의 같은 문법을 사용하며 특정 변수에 접근할 수 있는 다른 경로를 제공하는 레퍼런스 만듦.
  • 선언 방법: int& ref = var; 같이 자료형 뒤에 & 붙이기
    • ref의 값 변경하면 var 변수의 값도 변경됨
  • 포인터와 레퍼런스의 차이점
    1. 선언과 초기화 시점
      포인터는 선언 후, = 통해서 가리키는 대상 변경 가능
      레퍼런스는 선언과 동시에 초기화. 초기화 이후 다른 대상에 사용 불가능
    2. 레퍼런스에는 NULL 이 없다. 포인터는 유효하지 않음을 나타내기 위해 가끔 쓴다. nullptr 도.
    3. 간접 참조 문법
      포인터는 접근할 때 *, 주소 가져올 때 &
      레퍼런스는 변수 자체의 별명이라 일반 변수랑 똑같이 씀
  • 상수 레퍼런스 - 읽기 전용으로 레퍼런스를 쓸 때
    const int& cref = x;

HW 1

profile
개발지망생

0개의 댓글