변수 (Variable)

변수란 값을 저장할 수 있는 메모리 공간 자체 혹은 메모리 공간에 붙은 이름을 의미한다. 변수의 이름을 통해 값의 저장, 변경 및 참조가 가능하다.

Untitled

변수의 선언

변수는 다음과 같이 선언한다.

Type VarName;
Type VarName = Init_Value;

만약 변수를 선언하고 초기화하지 않으면 아무런 의미가 없는 쓰레기(Garbage) 값이 저장된다.

초기화(Initialization)란, 변수에 최초의 데이터를 할당하는 것을 의미한다.

int num; // num 이라는 이름의 변수 선언

위의 코드에서 intnum은 다음을 의미한다.

변수를 선언하고 변수의 이름을 통해 값을 저장하고 참조할 수 있다.

#include <iostream>

int main()
{
	int num = 0;    // num 이라는 이름의 변수 선언 및 0 으로 초기화
	num = 10;       // 변수 num 의 값을 10 으로 변경
	
	std::cout << num;    // 변수 num 의 값을 참조

	return 0;
}
10

이름 규칙

변수의 이름을 지을 때는 몇 가지 규칙이 있다.

int 7Val;     // 오류! 숫자로 시작
int return;   // 오류! 이름으로 키워드 사용
int Val!;     // 오류! 특수문자 포함
int Val One;  // 오류! 이름 사이에 공백

지역 / 전역 변수

변수는 선언되는 위치에 따라 전역 변수와 지역 변수로 나눌 수 있다.

지역 변수 (Local Variable)

전역 변수 (Global Variable)

#include <iostream>

// 전역 변수
int global_value;    // 초기 값 설정안했으므로 기본값(0) 으로 초기화

int main()
{
	{
		std::cout << "전역 변수 값 : " << global_value<< std::endl;
		
		// 지역 변수
		int value = 1;
		std::cout << "지역 변수 값 : " << value << std::endl;
	}
	
	// 오류! (블록을 벗어났으므로 지역변수 value는 사라짐)
	// std::cout << value << std::endl;
	std::cout << "전역 변수 값 : " << global_value<< std::endl;
	
	return 0;
}
전역 변수 값 : 0
지역 변수 값 : 1
전역 변수 값 : 0

초기값을 정해주지 않은 전역 변수 Global_Value 는 기본값 0 으로 자동 초기화되어 어느 곳에서도 사용이 가능했고, 지역 변수 Value 는 선언된 블록 안에서만 사용이 가능했다. 주석 처리된 블록 외부의 코드를 활성화한 경우 다음과 같은 오류가 발생한다.

Untitled


static 지역 변수

지역 변수에 static 선언이 붙게 되면 전역 변수의 성격을 지니는 변수가 되어 다음과 같은 특성을 지니게 된다.

#include <iostream>

void Func()
{
	static int num1 = 0;    // 한번만 초기화 됨!
	int num2 = 0;
	
	num1++;
	num2++;
	
	std::cout << "static 지역변수 : " << num1;
	std::cout << "       지역변수 : " << num2 << std::endl;
}

int main()
{
	for (int i = 0; i < 3; i++)
		Func();
		
	// num1 = 3; // 오류! 함수 밖에서는 접근 불가!
	
	return 0;
}
static 지역변수 : 1       지역변수 : 1
static 지역변수 : 2       지역변수 : 1
static 지역변수 : 3       지역변수 : 1

static 지역변수는 전역변수와 마찬가지로 프로그램이 종료될 때까지 메모리 공간에 남아있지만, 접근할 수 있는 범위를 제한할 수 있어 전역변수보다 안정적이다.


register 변수

지역 변수에 register 키워드가 붙게 되면 ‘레지스터’라는 메모리 공간에 저장될 확률이 높아진다. ‘레지스터’란 CPU 내에 존재하는 크기가 매우 작은 메모리로 그 안에 저장된 데이터를 대상으로 하는 연산은 매우 빠르게 동작한다.

void Func()
{
	register int num = 1;
	...
}

따라서 빈번히 사용하는 변수의 경우 register 선언을 이용해 접근이 가장 빠른 레지스터에 저장하도록 컴파일러에게 힌트를 전달할 수 있다. 그러나 최종 결정은 컴파일러가 내리며 register 선언을 추가해도 컴파일러가 합당하지 않다고 판단하면 레지스터에 할당되지 않는다.

반대로 아무런 선언을 하지 않아도 컴파일러가 레지스터에 할당해야겠다고 판단하면 그 변수는 레지스터에 할당된다.


상수 (Constant)

상수는 변수의 상대적인 개념으로 변경이 불가능한 데이터를 뜻하며 자료형을 근거로 표현된다. 상수는 크게 이름이 있는 상수와 이름이 없는 상수로 나뉜다.

리터럴(Literal) 상수

이름이 없는 상수를 가리켜 리터럴 상수 또는 리터럴 이라고 한다.

int num = 20 + 30;

위의 코드는 2030의 합의 결과를 변수 num에 저장하는 문장으로 덧셈 연산이 우선으로 진행되고 그 결과로 얻어진 값으로 변수 num을 초기화 한다. 즉, 20 + 30 연산을 CPU가 진행해야 하며 그러기 위해서는 2030이 메모리상에 존재해야 한다.

Untitled

위의 덧셈의 과정을 정리하면 다음과 같다.

여기서 변수 num 과 달리 상수들은 할당된 메모리 공간에 이름이 없다. 이러한 상수를 가리켜 ‘리터럴 상수’, ‘리터럴’ 이라고 한다.

2진수, 10진수, 16진수 리터럴

프로그래머는 일상에서와 다름없이 코드에도 10진수를 자주 사용하지만, 경우에 따라서는 2진수와 16진수를 다룰 일도 생긴다. 이때 접두사를 이용할 수 있다.

#include <iostream>

int main()
{
	unsigned int a = 240;          // 10 진수 리터럴
	std::cout << "a = " << a << std::endl;
	
	unsigned int b = 0b11110000;   // 2 진수 리터럴
	std::cout << "b = " << b << std::endl;
	
	unsigned int c = 0XF0;         // 16 진수 리터럴
	std::cout << "c = " << c << std::endl;
	
	unsigned int d = 0x1234abcd;   // 16 진수 리터럴
	std::cout << "d = " << d << std::endl;
	
	return 0;
}
a = 240
b = 240
c = 240
d = 305441741