[TIL] 23-12-13

Lev·2023년 12월 13일
0

📓TIL Archive

목록 보기
3/33

변수와 메모리

void MonsterMove() // 함수
{
	int MonsterSpeed = 1; // 변수
}

int main()
{
	MonsterMove(); // 실행!
}

대부분의 프로그래밍 언어, 그 중에서도 객체지향을 포함한 언어들은 개념, 행동, 상태로 인간이 만들고자 하는 것을 표현한다.

  • 개념 ⇒ e.g. 몬스터를 만들고 싶다
  • 행동 ⇒ 함수 e.g. 몬스터는 움직여야 한다
  • 상태 ⇒ 변수 e.g. 몬스터에게 속도를 부여해줘야 한다
int MonsterSpeed = 3;
int MonsterSpeed = 5; // 불가능!

같은 이름의 변수를 두 번 이상 선언할 수 없다.

  • 메모리 영역이 겹치기 때문
  • 정확하게 동일한 번지수(이미 차있음)에 새로운 공간을 생성하려는 것

지역변수

void MonsterMove()
{
	int MonsterSpeed = 3; // int MonsterMoveMonsterSpeed = 3;
}

int main()
{
	int MonsterSpeed = 3; // int mainMonsterSpeed = 3;

	MonsterMove();
}

이 경우에는 두가지 이유로 변수를 같은 이름으로 선언해도 빌드가 가능하다.

  1. 변수의 생략된 이름

    • 변수의 실제 이름에는 함수의 이름이 앞에 붙어 있다고 봐도 무방하기 때문
  2. 함수의 메모리

    • main 함수가 실행되면, 스택영역에 변수+a 만큼의 공간을 함수에게 할당한다.
      이 때 mainMonsterSpeed 변수가 main의 공간 안에 위치하게 된다.
    • MonsterMove 함수가 실행되면, 스택영역에 새로이 변수의 크기를 포함한 공간을 할당한다.
      이 때 MonsterMoveMonsterSpeed 변수가 MonsterMove 공간 안에 위치하게 된다.
    • 이렇게 함수 안에 만들어진 변수를 지역변수라고 부른다.

전역변수

#include <iostream>

// 전역 : 어떠한 { } 에도 속하지 않는 영역
int GlobalA = 10; // 전역변수

// 클래스 내부지역 : NOT YET

void Test()
{
	// 지역 : 함수의 { } 에 속하는 영역
	int LocalA = 10; // 지역변수
}

int main()
{
	Test();
    // 함수를 만들면 반드시 사용해보자!
    // 사용하지 않은 함수는 최적화에 의하여 빌드에 포함되지 않아 오류가 있는지 없는지 알 수 없다.
}
int MonsterSpeed = 10;

void MonsterMove()
{
	MonsterSpeed = 8;
}

int main()
{
	MonsterSpeed = 20;
}

전역변수는 어느 지역에서도 사용 가능하다.

  • 스택영역이 만들어지기 전부터 데이터영역에 할당되고
  • 프로그램이 종료되기 전에는 파괴되지 않기 때문

📢 코딩스탠다드 (추후에 추가!)
표기법 및 구분법을 각 회사나 프로젝트 상황에 맞추어 규칙을 정한 것 (가급적 유지하자!)
적어도 이 수업을 듣는 동안은… [구글 스타일 가이드 + 언리얼식]

1. 전역변수와 지역변수는 이름을 구분하여 작성할 것
2. 변수에는 반드시 초기값을 설정할 것

이름 없는 메모리 영역

{ } : 스코프 (레인지?)

  • 함수가 실행되면 메모리에 할당하라는 명령이 된다.
  • 마지막 중괄호를 만나면 스택영역에서 함수의 메모리를 삭제하라는 명령이 된다.
int main()
{
	// 이름 없는 메모리 영역을 만드는 것도 가능하다.
	{
		int Value = 0;
	}
	Value = 20; // 불가능!
}

스코프가 닫힐 때 할당된 메모리도 삭제되므로 지역 바깥에서는 사용할 수 없다.

int main()
{
	int Value = 0;
	{
		Value = 20; // 가능!
	}
}

이름없는 영역의 메모리는 main 함수의 메모리가 연장되는 형태이므로 이 경우에는 사용 가능하다.

연산자

변수를 사용해서 특정한 결과를 리턴하는 것

  • 연산자는 기본적으로 함수와 같다. (’행동’이기 때문에)
  • 무조건 같은 자료형끼리 구성되어야 한다. (Result도 같은 자료형)

💡 연산자의 종류
산술 연산자 / 비교 연산자 / 관계 연산자 / 비트 연산자
복합 할당 연산자 / 멤버와 포인터 연산자 (포인터 배운 이후에) / 기타 연산자


변수의 개수에 따라서 분류할 수도 있다.
- 단항 연산자 : 변수가 1개 필요한 연산자 e.g. !Left;
- 이항 연산자 : 변수가 2개 필요한 연산자 e.g. Left + Right;
- 삼항 연산자 : 변수가 3개 필요한 연산자 (딱 한 종류 뿐!) e.g. Left == Right ? true : false;

📢 코드 읽기 규칙
1. 기본적으로 위에서부터 아래로 읽는다.
2. 오른쪽에서 왼쪽으로 읽는다.

int Left = 3;
/*
1. 3을 준비한다
2. 대입연산자를 준비한다 
3. left를 만든다
4. 대입한다
*/
  1. (2)에서 예외 : ( ) 안에 있는 내용은 우선적으로 진행된다.

산술 연산자

int Left = 3;
int Right = 5;
int Result = 0;
// [대입] : 오른쪽의 메모리를 왼쪽의 메모리로 복사한다.
Left = Right; // 5
Result = Left + Right; // 8 => [덧셈]
Result = Left - Right; // -2 => [뺄셈]
Result = Left * Right; // 15 => [곱셈]
Result = Left / Right; // 0 => [나눗셈(몫)]
Result = Left % Right; // 3 => [나머지]

비교 연산자

// [논리형 상수 bool] => true와 false가 있다.
bool bResult = false;
bResult = Left == Right; // false
bResult = Left != Right; // true
bResult = Left > Right; // false
bResult = Left < Right; // true
bResult = Left >= Right; // false
bResult = Left <= Right; // true
Result = Left == Right; // 0
// 사실 이렇게 정수로 결과값을 받을 수도 있다. => true 1, false 0
// 하지만 정수(int)는 4byte, 논리형(bool)은 1byte라는 차이가 있고, bool로 받는게 정석이다.

논리 연산자

자료형을 비트 단위로 생각하는 것이 중요하다. (1 byte = 8 bit)
참 ⇒ 단 하나의 비트라도 1일 때
거짓 ⇒ 모든 비트가 0일 때

bResult = Left; // true
bResult = 0; // false
// 오로지 0만이 거짓이고, 나머지 모든 숫자는 참이다.
// 따라서 모든 값은 논리형이 될 수 있다.
// [논리 부정]
bResult = !Left; // false

// [논리적 AND] : 왼쪽과 오른쪽 메모리가 모두 true여야 true
bResult = Left && Right; // true
bResult = false && Right; // false
bResult = Left && false; // false
bResult = false && false; // false

// [논리적 OR] :: 왼쪽과 오른쪽 메모리 중 한쪽이라도 true면 true
bResult = Left || Right; // true
bResult = false || Right; // true
bResult = Left || false; // true
bResult = false || false; // false

비트 연산자

정수의 비트표현식을 이해해야 한다.
int ⇒ 4 byte = 32 bit

Left = 0b00000000000000000000000000000000; // 2진수(binary)로 표현하겠다는 뜻

// [보수]
Left = ~0b00000000000000000000000000000000; // 0b11111111111111111111111111111111 // -1

💡 2의 보수법
비트로 음수를 표현하기 위해, 가장 앞의 비트(부호비트)가 1일 때가 음수라고 정해두었다.
하지만 -0 이라는 숫자는 존재하지 않기 때문에, 2의 보수법을 사용하기로 했다.

1. 가장 앞 비트가 1인 경우, 음수이다.
2. 나머지 비트를 모두 반전시킨다. (0 → 1, 1 → 0)
3. 나머지 비트를 모두 더한 숫자에 1을 더해준다.
4. (3)의 결과물을 음수로 변환하면 짜잔!
Left = 0b00000000000000000000000000000011;
Right = 0b00000000000000000000000000000001;

// 비트 AND : 왼쪽과 오른쪽을 비교해서 둘 다 1이어야 1
Result = Left & Right; // 0b00000000000000000000000000000001 // 1

// 비트 OR : 왼쪽과 오른쪽을 비교해서 둘 중 하나만 1이어도 1
Result = Left | Right; // 0b00000000000000000000000000000011 // 3

// 배타적 논리합 : 양쪽의 비트가 같으면 0, 양쪽의 비트가 다르면 1
Result = Left ^ Right; // 0b00000000000000000000000000000010 // 2

// 비트 시프트
Result = Left << 1; // 0b00000000000000000000000000000010 // 2
Result = Left >> 1; // 0b00000000000000000000000000000000 or 0b10000000000000000000000000000000
// CPU 칩셋, 또는 VS 설정 등에 따라 결과가 달라질 수 있다.
// 아무튼 비트가 손상(?)될 수 있을만한 경우에 시프트 연산은 사용하지 않는 편이 편하다...

비트 연산은 클라이언트보다는, 대규모 유저를 감당해야 하는 서버 파트에서 좀 더 중요하다.

  • 장점 : 다른 자료형을 사용한 연산보다 월등하게 메모리를 아낄 수 있다.
  • 단점 : 코드의 가시성이 떨어진다.

과제

// Q) 비트 연산으로 -1을 만들고, 그걸 이용해서 int의 양수 최대값과 음수 최소값을 만들어보자.

int main()
{
    int a = 0; // 0b 00000000 00000000 00000000 00000000
    int result = 0;

    int b = ~a; // 0b 11111111 11111111 11111111 11111111 => -1
    a = b << 31; // 0b 10000000 00000000 00000000 00000000 => 음수 최소값

    result = a ^ b; // 0b 01111111 11111111 11111111 11111111 => 양수 최대값
    // 왜인지 왼쪽으로 비트를 밀어버리는건 생각하는대로 작동한다?!

    return 0;
}

📢 중단점과 디버깅
코드를 보다가 현재까지 진행한 단계와 그 상태에서의 값을 확인하고 싶을 때, 확인하고 싶은 코드 라인 1줄 아래에서 F9을 누르면 중단점이 걸린다. (빨간 점)
실행 대기 중인 라인은 노란 화살표로 표시되어 있다.

이 때, VS로 코드를 실행시키고 확인하기 위한 단축키도 여러 종류가 있다.
F5 ⇒ 중단점까지 진행
F10 ⇒ 한줄씩 진행, but 다른 함수의 스택에 들어가지 않는다.
F11 ⇒ 한줄씩 진행, 다른 함수가 있다면 그 함수의 내부스택까지 들어간다.

F10, F11을 이용하면 아무리 복잡한 프로세스여도 시작 지점(진입점)을 알 수 있어 유용하다.
그리고 중간중간 값을 확인하는 습관은 기본 중의 기본이다!


📚 오늘의 자투리 지식

  • 잊지 말자 기초 지식!
    - 윈도우 재설치하는 법
    - 하드디스크 초기화, 인식시키는 법

    	1. 하드디스크 파티션 만들기 및 포맷
    	2. (인식 안된) 디스크 초기화
    	3. mrv 디스크로 변환
    	4. 새 스팬 볼륨?
  • C++의 버전
    - C++는 연도로 버전을 구분한다.
    - VS의 C++ 컴파일러는 C++ 표준과 아주 사알짝 다르다.

profile
⋆꙳⊹⋰ 𓇼⋆ 𝑻𝑰𝑳 𝑨𝑹𝑪𝑯𝑰𝑽𝑬 ⸝·⸝⋆꙳⊹⋰

0개의 댓글