모두의 코드 - 3. 변수가 뭐지?

2024. 9. 21. 12:35Programming Language/C

3. 변수가 뭐지?

변수란 무엇인가?

컴퓨터는 많은 내용을 기억해야한다.

게시판만 하더라도 글번호, 제목, 작성자등등의 내용을 기억하고 있어야만 제대로 된 게시판을 보여줄 수 있을 것이다.

그렇다면 컴퓨터는 이러한 내용(데이터)들을 어떻게 기억할까.

컴퓨터의 메모리, 즉 램(RAM)이라는 특별한 기억공간에 기록한다

흔히 램을 설명하기 위해서 아래 처럼 된 모형을 사용한다.

각 방에 데이터들이 저장되고 각 방마다 이름을 붙이는데 단순하게 숫자로 이름을 붙인다.

0번, 1번, 2번..과 같이 말이다.

우리 대부분이 사용하는 32비트 CPU에서는 최대 232개(4GB), 약 42억개에 달하는 방을 가질 수 있다.

참고로 32비트 숫자를 매번 쓰는게 힘들기에 대개 16진법으로 주소값을 나타낸다.

 

예를 들어 0x12345678 부터 0x1234567B 부분에 어떤 정보를 저장 했다면(이 한칸에는 1바이트, 즉 -128 부터 127까지의 수 데이터를 저장할 수 있다) 우리가 이 정보를 필요로 할 때마다 복잡한 주소를 일일이 써야하는 복잡한 상황이 발생할것을 대비해서 C언어는 변수라는 대비책을 사용할 수 있다.

 

내가 어떤 데이터를 mineral이라는 변수에 저장했다고 한다면, 컴퓨터는 알아서 메모리의 어딘가에 mineral 에 방을 주고 그 내용을 저장한다.

예를 들어 4칸의 자리를 할당하면 아래와 같은 형태가 된다.

이렇게 C언어에서는 바뀔 수 있는 어떤 값을 보관하는 곳을 변수 라고 한다.

영어로는 Variable이라고 하고 이는 바뀔 수 있는 것을 의미한다.

 

변수 선언하기

 

이렇게 코드를 작성해서 컴파일을 해보자

 

** 컴파일 단축키 - ctrl + shift + b or ctrl + F7

** 실행 단축키 -  ctrl + F5

와 같이 나온다

 

이번에도 한문장씩 차근 차근 알아보자.

 

int a;

 

이건 a라는 변수를 우리가 쓰겠다고 컴파일러 한테 알리는 것이다.

그리고 a앞에 붙은 int라는 것은 int형의 데이터를 보관한다는 의미로 a에 -2147483648부터 2147483647까지의 범위의 정수를 보관하겠다라는 의미이다.

 

그래서 그 다음에 나오는 

 

a = 10;

 

이란 문장을 

라고 한다면 저장 범위를 넘기기에 

이렇게 원하지 않는 값이 나오게 된다.

 

그러면 a에 고작 10 넣으면서 왜 int형 변수를 사용했냐고 물을 수 있다.

물론 int형보다 작은 범위의 숫자 데이터만을 가지는 형식이 있으나, 일반적으로 정수 데이터를 보관할 때 int형 변수를 사용한다.

 

또 int형보다 더 큰수를 저장할수도 있는데 아래에 데이터형식에 따른 표를 한번 확인해보자.

타입크기범위

타입 크기 범위
char 1 바이트 unsigned char 의 경우 0 부터 255, signed char (그냥 char) 의 경우 -128 부터 127 까지
short 최소 2 바이트 2 바이트일 경우 signed short 는 -32,768 에서 32,767. unsigned short 는 0 부터 65,535 까지
int 최소 2 바이트 이고 보통 시스템의 경우 4 바이트로 구현된다. 4 바이트 일 경우 signed int 의 경우 -2,147,483,648 에서 2,147,483,647 까지. unsigned int 의 경우 0 부터 4,294,967,295 까지
long 최소 4 바이트. 32 비트 시스템의 경우 4 바이트, 64 비트 시스템에선 보통 8 바이트  
long long 최소 8 바이트 8 바이트일 경우 signed long long 는 -9223372036854775808 부터 9223372036854775807 까지. unsigned long long 는 0 에서 18446744073709551615 (대략 1.84×1019) 까지
float 4 바이트  부터  까지. 정밀도는 대략 10진수로 6 자리 정도
double 8 바이트  부터  까지. 정밀도는 대략 10진수로 15 자리 정도
long double
8 바이트 이상 double 이상의 표현범위

 

한가지 중요한 점은 각 타입들의 크기는 char, float, double 말고 정확히 정해진 것은 없다.

예를 들어 int의 경우는 C표준을 읽어보면 최소 2바이트인 타입으로 써져 있지 몇 바이트로 해라 라고 써져있지는 않는다.

하지만 대부분 int는 4바이트로 구현되어 있다.

 

그리고 범위를 보면 unsigned와 signed라고 나뉜 것을 볼 수 있는데 보통 int는 signed int를 의미한다.

이는 음수 양수 모두 표현 할 수 있는 대신 양수로 표현할 수 있는 범위가 줄어든다.

 

반면에 unsigned int는 양수만을 표현할 수 있는 대신에 양수를 표현할 수 있는 범위가 두배로 늘어난다.

그리고 아래쪽에 float, double, long double이 있는데 이들은 "실수형"자료형으로 소수(0.1, 1.234 등)을 표현할 수 있다.

뿐만 아니라 double의 경우는 ±2.3×10−308 부터 ±1.7×10308의 수를 표현할 수 있다.

 

그럼 a = 10; 은 무엇을 의미할까?

변수 a에 10을 넣겠다는 의미이다

마지막으로 

 

printf("a의 값은: %d \n", a);

 

는 저번에도 보았던 printf인데 다른 점은 %d가 출력되는 부분에 써져 있는데 프로그램을 실행시켜봤을때 %d는 컴퓨터에 출력되지 않는다.

대신 %d가 출력된 자리에 a의 값이 출력되고 있는데 %d는 a의 값(정확하게는 ""뒤에 초는 첫번째 변수)을 10진수로 출력하라는 의미가 된다.

 

다른 예제를 보자.

이를 실행해보면 

와 같은 결과값을 볼 수 있다.

 

printf의 동작 방식은 %가 달린 것의 순서에 맞게 그 뒤로 나오는 인자를 순차적으로 접근해서 사용한다

 

printf("a의 값은 %d 진수로 %o 입니다. \n", 8, a);

 

라면 

%가 붙은 문자는 %d, %o이고 그 문자열 뒤로 8, a가 인자로 붙는다

그러면 %d에는 8이 들어가게 되고 %o에는 a가 들어가게 된다.

 

그러면 

 

printf("%d %d %d  %d \n", a, b, c, d);

 

라면 %가 붙은 문자에 순서대로 a, b, c, d가 들어가서 출력될 것이다.

 

그려면 %o와 %x는 무엇일까?

이는 인자의 값을 출력하는 형식으로 %o의 경우는 들어올 인자의 값(위의 예로는 a)을 8진수로 출력하라는 의미이고, %x의 경우는 16진수로 출력하라는 의미가 된다.

 

실수형 변수

앞에서 말했듯 실수형에는 float와 double이 있다.

double의 경우는 int형에 비해 크기가 2배나 크지만 그 만큼 큰 수를 다룰 수 있다.

대신 처음15개의 숫자들만 정확하고 나머지는 10의 지수 형태로 표현된다.

또한 float와 double의 장점은 소수를 표시할 수 있다는 점인데, 정수형 변수에서 소수를 넣는다면(int a; a =1.234) 소수부분은 다 달라내고 정수 부분만 저장된다.

이를 실행해보면 

와 같은 결과 값을 볼 수 있다.

 

일단 이 코드에서 궁금한 점은

a 의 경우는 선언시에 f를 붙이는데 double의 경우는 왜 안붙었을까?

이는 float형의 경우는 f를 안붙여주면 double형으로 인식해서 문제를 발생할 수 도 있기 때문이다.

float형임을 확실하게 표시해주는 방법이다.

 

그리고 이제 출력 부에 대한 궁금증이다.

이번엔 %f가 나왔는데 그러면 여기서 %d로 출력한다면 어떻게 될까?

아예 뜬금 없는 이상한 숫자가 나온다.

 

우리가 변수에 값을 할당할때 정수를 넣어준다 하더라도(a = 1; b = 2;) a와 b에 이미 실수형 타입임을 선언 했기 때문에 절대 정수로 봐주지 않는다. 

그렇기에 실수형 변수를 출력할때는 %f의 형식을 사용해야만 한다.

주의할 점은 printf에서 %f로 수를 출력할때는 언제나 뒤에 소수점을 붙여줘야 한다는 점이다.

이렇게 해서 출력해보면 

%f에 소수점을 넣지 않고 정수형 데이터를 출력하려고 하면 예상하지 못한 값이 출력 되지만 소수점을 넣은 실수형 데이터를 출력하려고 하면 잘 출력이 되는 것을 볼 수 있다.

 

printf의 또 다른 형식

 

위 코드를 실행해보면 

이런 결과 값을 확인할 수 있을 것이다.

 

먼저 이번에는 그냥 %f가 아니라 %.2f로 조금 다른 방법을 사용했다.

%와 f사이에 들어가는 실수형 숫자에서의 의미는 .2처럼 사용한 경우에 뒤에 나오는 인자가 이 내부로 들어와 출력될 때 소수점 2자리 수까지만 보여줘라 라는 의미이다.

%.100f의 경우도 소수점 아래 100번째 숫자까지 보여줘라 라는 의미인데 우리가 넣은 3.141592의 경우는 100자리가 안되기 때문에 자릿수 이후로는 0을 채워서 무조건 100자리 숫자를 모두 출력한다.

 

이것도 %d가 아니라 %5d 인데 여기서는 .5와 같이 소수점을 넣어주는게 아니라 정수를 넣어준다.

그리고 이 의미는 숫자의 자릿수를 5자리로 맞추라는 의미이다.

123이라는 값을 표현 하는 경우는 5자리가 되지 않기 때문에 공백 2칸을 앞에 넣어 "  123"으로 출력했다.

그러면 위의 %f의 경우와는 반대로 출력하는 수의 자릿수가 우리가 요구하는 자릿수를 초과하는 경우는 어떨까?

이렇게 7자릿수로 만들어 동일하게 출력해보자.

여기서는 그냥 그대로 출력해준다.

%.?f의 경우는 무조건적인 조건이지만 %?d의 경우는 반드시 지켜져야하는 것은 아니다.

 

마지막으로 위에서 사용했던 방법을 한번에 사용한 모습이다.

실수형 데이터를 6자리로 되도록이면 만들고(초과된다면 초과된대로 보여주나 자릿수가 초과되지 않는다면 공백을 앞에 추가해서 출력해라), 무조건 소수점 3번째 자릿수까지 출력해서 보여주고 혹여나 소수점이 3자리를 넘기지 않는다면 0을 뒤에 추가해서라도 출력해라라는 의미가 된다.

 

변수 작명하기

위에서 봤듯이 변수를 선언하는것은 어려운 일은 아니다.

그대신 아래의 형태로 맞춰 주기만 하면 된다.

이때 주의할 점은 오래된 버전의 C언어(C89)를 사용하는 경우라면 변수는 항상 최상단에서 선언해줘야한다.

최신 버전의 경우는 아무데나 선언해도 문제를 발생시키지는 않는다.

 

변수를 생성할때는 아래의 작성법에 따라서 작성해줘야 한다.

  • 변수를 작성할때는 숫자가 맨 앞에 위치해서는 안된다.(중간이나 마지막은 무관)
  • 변수명은 영어, 숫자, _ 로만 구성되어 있어야한다.(비주얼 스튜디오같은 컴파일러의 경우는 유니코드(한글포함)로 변수이름을 작성해도 문제는 없는데 관습상 코드는 모두 영어로 작성하는게 좋다 )
  • 변수의 이름에 띄어쓰기를 허용하지 않는다
  • 변수의 이름이 C언어 예약어이면 안된다. 보통 예약어를 쓰면 에디터에서 다른 색상으로 표시되어 구분이 가능하다.
  • 대소문자를 구분한다(이걸 영어로 case sensitive라고 함).

좋은 변수명

프로그래밍을 하면서 변수는 수없이 생성하게 된다.

많이 생성할수록 관리가 힘들어지기 때문에 변수명은 아무렇게나 만들어서는 코드의 이해를 어렵게 만들게 된다.

그렇기에 변수명을 보았을때 이 변수가 어떤 값을 갖고 있겠구나 유추될 수 있도록 직관적으로 작성하는게 좋다.

a, b, c가 어떤 용도로 사용되는지 알수 있겠는가?

그러나 num_students와 total_score의 경우는 한번에 학생의 수와 총 점수를 나타내는 변수임을 확인할 수 있다.

 

간단히 주관적인 관점에서 좋은 변수명의 경우는 아래와 같다.

  • 담은 데이터가 어떤 용도임을 알 수 있어야 한다.
  • 영어로 읽을 수 있도록 해야한다(한국말을 영어로 풀어쓰는 경우는 좋지 않음)
  • 일관된 코드 스타일을 가져야한다.

코드 스타일의 경우는 _를 사용하는 snake case와 대소문자를 통해서 단어와 단어를 구분하는 camel case로 나뉜다.

 

snake case

 

camel case