Qaupot Blog
Software Engineering, Trip

203. 변수와 선언

🕐 Sun, 26 Jan 2014 09:00:00 GMT 🕓 Fri, 20 Aug 2021 10:12:00 GMT

변수 (Variable)

변수는 어떤 관계나 범위에서 여러 값으로 변할 수 있는 수 입니다.
f(x) = x + 1 수식에서,

  • x 가 변수 입니다.
  • x 는 어떠한 값으로든 변할 수 있다는 사실을 의미합니다.

변수의 필요성

Computer 는 무엇인가를 계산하기 위한 장치이며, 프로그램은 어떠한 결과를 산출하기 위해 작성합니다.
산출물은 단순한 수치 값이 아닌 게임이나 영상물이 될 수도 있습니다.

변수가 없어도 우리는 프로그램을 작성할 수 있습니다.
1 + 1을 계산하는 프로그램을 만들었다고 하면, 이 프로그램은 항상 결과값 2를 도출합니다.

하지만 1 + 2를 계산할 필요가 생겼다면, 다시 새롭게 프로그램을 작성 해야만 합니다.

변수의 존재는 프로그램에 유연성을 가져다 줍니다. 입력되는 값에 의해 다른 결과를 도출해 낼 수 있습니다.

변수는 중간 데이터들을 보관하는 장소의 역할도 가지고 있습니다.

사람은 복잡한 식을 계산할 때, 종이를 펼처두고 그 중간 결과를 적어가며 계산을 할 수 있습니다. 이와 마찬가지로, CPU 가 기억할 수 있는 값들은 매우 한정적이며, 비싼 자원입니다. 따라서, 복잡한 프로그램일수록 메모리 상에 데이터들을 기록해 둘 필요가 있으며, 그 데이터를 기록해 둘 변수들의 필요성은 커진다고 할 수 있습니다.

변수의 선언법

#include <stdio.h>

int main(int argc, char** argv)
{
	int variable;
	printf("Hello World\n");
	return 0;
}

기존에 작성했던 Hello World 에 'int variable;' 한줄을 추가했습니다.

키워드 이름 구두점
int variable ;
자료형 새 이름 세미콜론

컴파일러는 해당 자료형의 크기만큼 비어있는 공간을 만들고, 지정된 이름을 붙여줍니다.
위의 'int Variable;' 은 int 가 자료형, Variable 이 이름, 그리고 ;이 마침표에 해당합니다.

명칭은 다른 이름이나 키워드와 중복되지 않는다면 어떤 것을 사용해도 괜찮습니다.
프로그램 작성 초반에는 단순한 a, b, c등을 쓸 지도 모르지만, 변수의 쓰임새가 표현되는 이름을 짓는 것이 좋습니다.

예) 간단한 변수명

#include <stdio.h>

int main(int argc,char** argv)
{
    int a = 1;
    int b = 2;
    printf("%d\n",a+b);
    return 0;
}

예) 의미가 포함된 변수명

#include <stdio.h>

int main(int argc,char** argv)
{
    int leftOperand = 1;
    int rightOperand = 2;
    printf("%d\n",leftOperand + rightOperand);
    return 0;
}

나중에 다시 프로그램 코드를 살펴 볼 때, 이러한 작명은 큰 도움이 됩니다.

C 에서 변수의 선언은 함수 내에서 가장 처음에 등장해야 합니다.

  • C++ 에서는 제약을 받지 않습니다. - 사용하기 전에만 선언하면 됩니다.

변수의 수명

#include <stdio.h>

int main(int argc,char** argv)
{
	int Variable1 = 10;
	{
		int Variable2 = 20;
		printf("%d %d\n",Variable1,Variable2);
	}

	printf("%d",Variable1);

	// 다음 코드를 넣으면 에러가 발생합니다.
	//printf("%d %d\n",Variable1,Variable2);
}

// 로 시작하는 코드는 주석문(Comment) 이라고 하며, 컴파일러는 해당 줄을 무시합니다. 에러가 발생하는 코드를 적어두기 위해 사용하였습니다.

Variable1 과 Variable2 변수가 선언되어 있습니다.
Variable1 은 main 함수의 {} 안에, Variable2 는 그 안에서도 {}로 한번 더 감싸고 있습니다.

C / C++ 에서 가장 기본적으로 범위 (Scope) 를 구분짓는 방법은 {}이며, 변수의 수명은 대부분 { } 에 의해 결정됩니다.
main 함수의 {} 범위안에 존재하는 변수 Variable1 은 main 함수가 소멸할때까지 그 수명이 유지됩니다.

그리고 main 함수 내에서 다시 { } 로 묶인 범위가 있습니다. 이 안에서는 Variable2 가 선언되어 있습니다.
이 범위 내에서는 자신의 상위 범위인 main 함수 범위 및 자기 자신범위 내에 있는 변수를 사용할 수 있습니다.
즉, 여기서는 Variable1과 Variable2를 전부 사용할 수 있습니다.

그리고 범위가 끝나면서 Variable2는 그 수명이 다 하게 됩니다. 다시 main 함수 범위로 돌아갑니다.
여기서는 이미 범위가 끝나버려 수명이 다한 Variable2 를 사용할 수 없습니다.
이렇게 단기적, 지역적으로 사용 되고 수명이 한정적인 변수를 "지역 변수" 라고 합니다.

Variable1 와 Variable2 는 모두 지역변수입니다.

#include <stdio.h>

int GlobalVariable;

int main(int argc,char** argv)
{
	GlobalVariable = 20;

	printf("%d",GlobalVariable);
}

위의 코드는 변수를 함수의 바깥에 선언해 본 모습이며, 어떠한 {} 로도 둘러싸여 있지 않습니다.
이를 "전역 변수"라 하며, 최상위 범위에 속하게 됩니다.
다시 말해, 이러한 변수는 같은 코드내의 모든 범위내에서 사용할 수 있습니다.

또한 프로그램이 종료될 때까지 수명이 유지됩니다. 그러나 이러한 방법은 되도록 사용하지 않는 것이 좋습니다.

이러한 전역변수들은 당장은 편리할 지 모르나, 코드의 유지보수를 어렵게 만듭니다.
지역 변수는 해당 지역내에서만 사용되므로, 사용 범위를 파악하기 쉽지만
전역 변수는 어디서든 사용할 수 있으므로 어디서 이 변수를 참조하고 있는지 파악하기 어렵습니다.

변수의 선언에 덧 붙일수 있는 키워드 - static

#include <stdio.h>

void Prints()
{
	static int StaticVariable = 0;
	StaticVariable = StaticVariable + 2;
	printf("%d\n",StaticVariable);
}

int main(int argc,char** argv)
{	
	 Prints();
	 Prints();
}

변수의 선언문법에 static 키워드를 덧 붙일 수 있습니다. 이 키워드는 해당하는 변수를 "정적 변수"로 만들어 줍니다.

  • 선언문의 앞에 붙습니다

정적 변수의 수명은 전역 변수 처럼 프로그램이 종료될 때 까지 유지됩니다만,
사용할 수 있는 범위는 이 변수를 선언한 범위와 그 이하 범위들로 제한됩니다.

Print 함수를 두 번 호출했으며, 실행 시 값이 +2 되며 유지 되는 것을 확인할 수 있습니다.

변수의 선언에 덧 붙일수 있는 키워드 - register

#include <stdio.h>

int main(int argc,char** argv)
{	
	register int RegVar = 30;

	printf("%d",RegVar);
}

변수의 선언문법에 register 키워드를 덧 붙일 수 있습니다. (선언문의 앞에 붙습니다)
이 키워드는 해당하는 변수를 "레지스터 변수"로 만들어 줍니다.

레지스터는 CPU 에 존재하고 있는 매우 빠르면서도 한정적인 메모리 공간입니다. 이러한 레지스터는 CPU 내에 상당한 크기가 포함되어 있지만, 우리가 직접적으로 프로그램으로 다룰 수 있는 범용 레지스터는 몇 개 되지 않습니다.

레지스터 변수는 명시적으로 컴파일러에게 레지스터를 사용하도록 지시하는 방법입니다.
자주 사용되는 변수를 레지스터에 할당되도록 지정하면 성능을 높일 수 있습니다.

그러나 컴파일러는 최적화 여부, 레지스터를 할당할 수 있는지에 대해서 판단한 뒤 이를 무시하고 메모리에 할당할 수도 있습니다.
일반적인 경우, register 키워드를 쓰지 않고 컴파일러의 최적화 작업을 통해 적당한 레지스터에 배치되도록 놔 두는게 바람직합니다.

  • double 형은 64bit 으로, 32bit 레지스터에 할당할 수는 없습니다.

Auto (C++11)

#include <stdio.h>

int main(int argc,char** argv)
{	
	auto AutoVar1 = 30;

	printf("%d %f",AutoVar1,AutoVar2);
}

여러분이 C++11을 지원하는 컴파일러를 사용하시고 계시다면 변수의 선언시에 자료형 대신 auto 키워드를 사용할 수 있습니다.

auto 키워드는 초기화 값 (위의 경우는 30)에 따라서 컴파일러가 자료형을 유추합니다.

위의 경우는 아마도 int 가 추정되겠지만, 어디까지나 '유추' 이므로 우리가 원하는 자료형이 아닐수도 있습니다.
30은 double 이나 float 으로도 표현할 수 있지만 int 가 추정되는 이유는 가장 합당하기 때문일 것입니다.

auto 는 런타임(프로그램 실행 중)상에서 결정되는 것이 아니라는 점에 주의하셔야 합니다. 어떤 프로그래밍 언어들은 자료형을 따로 구분하지 않거나, 런타임 중에 명칭에 대한 자료형을 변경하는것이 허용됩니다.

C/C++에서 auto 키워드는 컴파일시에 특정한 자료형으로 치환됩니다. 따라서 위 예제 코드 처럼 선언 후에 AutoVar1 = 0.1f를 대입하면 int 형에 실수형을 대입하는 상황이 되므로 문법적 에러 메세지가 발생합니다.

이 블로그는 개인 블로그입니다. 게시글은 오류를 포함하고 있을 수 있지만, 저자는 오류를 해결하기 위해 노력하고 있습니다.
게시글에 별도의 고지가 없는 경우, 크리에이티브 커먼즈 저작자표시-비영리-변경금지 4.0 라이선스를 따릅니다.

This blog is personal blog. published posts may contain some errors, but author doing efforts to clear errors.
If post have not notice of license, it under creative commons Attribution-NonCommercial-NoDerivatives 4.0.