본문 바로가기
C

[C] 변수 | 변수란, 변수 선언, 자료형, 데이터 입출력

by Lizzie Oh 2022. 10. 21.

변수 

변수, '변경 가능한 수'를 가지려면 이를 담고 있을 메모리 공간이 필요한데, 변수란 이 메모리 공간에 붙여진 이름이다. 

 

메모리는 각 구조상 바이트별로 고유한 주소를 가지고 있어서, 이 주소를 대상으로 값을 읽고 쓸 수 있다. 프로그래밍 시 직접 메모리 주소를 사용하여 데이터를 제어하기는 어려우므로 이름을 붙여서(=변수를 부여하여) 제어하는 것! 

 

아래 왼쪽 그림을 보자. 4바이트의 메모리에 값을 저장할때 0x1000부터 1x1003 (메모리 주소는 16진수로 되어있다) 까지 저장한다고 해보자. 이 주소들을 매번 외워서 사용하는 번거로움을 피하기 위해 오른쪽 그림 처럼 0x1000부터 1x1003 의 이름은 a 야! 라고 a라는 변수를 통해 메모리에 이름을 붙여주는 것이다. 

이렇게, 우리는 변수를 통해 메모리에 접근해서 데이터 입출력을 용이하게 할 수 있다.

변수의 종류 - 자료형 

변수는 저장된 메모리 위치와 함께, 변수의 길이와 형태에 대한 정보, 즉 자료형(data type)을 가진다. 변수를 선언할 때 항상 이 자료형을 명시하도록 되어 있어서, 컴파일러는 이 자료형을 통해 변수의 형태와 메모리를 얼마나 할당할 지 등의 정보를 파악할 수 있다. 

 

C언어의 자료형은 기본형과 유도형으로 나뉘어 있다. 

  • 기본형: 정수형(short, int, long), 문자형(char), 실수형(float, double)
  • 유도형: 배열형([]), 포인터형(*), 구조체형(struct)

변수의 선언

자료형 변수명;  형태로 변수 선언  e.g. int value ;

변수 선언 후 값을 대입(int value;  value = 5;)할 수 도 있지만, 선언과 동시에 초기화 할 수 있다  e.g. int num = 5; 

 

선언과 동시에 초기화하는 것이 더 권고되는데, 그 이유는 변수를 선언'만' 하면 해당 변수는 비어있는 게 아니라 자동으로 쓰레기값(garbage)이 들어간 상태가 되기 때문에 메모리 관련한 버그의 발생 가능성이 생기기 때문이다! (실제로 컴파일러에서 빌드시 오류를 잡아내는 레벨을 설정할 수 있는데, 변수의 초기화를 하지 않는 구문을 경고나 에러로 잡아내기도 한다고 한다)

 

🚨 C언어 변수 선언 시 주의할 점은 변수 선언이 가장 먼저 이루어져야 한다는 것이다! (C언어만의 엄격한 문법 특징임) 
 - 변수 선언이 프로그램 중간에 나오면 안 되며, 변수를 초기화 하는 구문 역시 모든 변수의 선언이 이루어진 후에 등장해야 한다. 

#include <stdio.h>

int main(void) 
{
    int value ;
    value = 100; ##### 아래 char ch; 변수를 선언하기 전에 변수 초기화가 먼저 되므로 에러 발생 
    
	char ch;
    ch= 'C';
    
    return 0 
}

위의 코드는 다른 프로그래밍 언어라면 아무 문제가 없는 코드이지만 C에서는 컴파일러가 에러로 간주한다. 아래 코드는 에러가 발생하지 않는 정상 구문이다. 

#include <stdio.h>

int main(void) 
{
    int value ;
    char ch;
    
    value = 100;
    ch= 'C';
    
    return 0 
}

 

C언어 변수명 규칙

변수명은 알파벳, 숫자, 언더바로만 구성될 수 있고(공백 X, 특수문자X), 변수의 첫 문자는 숫자가 될 수 없다. 
알파벳은 대소문자가 모두 가능하나 두 문자는 구분되어 서로 다른 문자로 간주된다 e.g. num과 Num은 서로 다른 변수

 

데이터 출력

C언어에서는 prinf()를 통해 데이터를 출력하는데, 마지막 문자인 f는 formatting을 의미한다. 즉 printf 는 '서식화된 출력'을 한다.

즉 아래 표와 같은 서식 문자들을 사용할 수 있는 것이며 변수의 값이 서식문자에 맞는 출력 형태로 출력된다. 

예를 들어, int value = 100int ch= 'C'; 로 두 변수를 초기화 한 후 prinft("정수 %d, 문자 %c \n", value, ch); 와 같이 사용하면
→  "정수 100 문자 C" 가 출력된다. 

 

즉 printf() 의 첫번째 인수 " " 내에 %d, %c와 같은 서식문자가 존재하면,  이후의 인수인 변수 값들이 순서대로 각 서식문자에 대응되어, 서식문자에 맞는 출력 형태로 출력된다. (물론 서식 문자가 없으면 printf("Hello world \n")와 같이 하나의 인수만으로 prinf를 사용할 수 있다) 

 

기본형 자료형의 종류 및 표현 범위

아래 표는 C 자료형의 종류와 범위이다. 정수형 타입에는  char, short, int, long이 있고, 실수형 타입에는 float, double, long double이 있다. 노란색 하이라이트를 한 타입들이 일반적으로 많이 사용하는 자료형이다. 

https://medium.com/@MA/c-programming-8319b3878459 **long double의 크기는 10~16까지 가능

표에서 볼 수 있는 것처럼 자료형마다 메모리에 할당되는 크기가 다르다. 메모리 크기가 클 수록 표현할 수 있는 데이터가 커진다. 애초에 이렇게 다양한 자료형을 나눠 놓은 이유도 최대한 효율적으로 메모리를 사용하기 위해서이다. 우리가 안경을 담으려고 32인치 캐리어를 들지 않듯이, 작은 데이터를 담을 때는 적은 메모리를 할당해야 한정된 메모리 자원을 효율적으로 사용할 수 있다! 

 

sizeof 연산자

피연산자로 자료형의 이름이 올 경우 반드시 () 를 사용 : sizeof(int)

피연산자로 변수 이름이 올 경우 ()를 써도 되고, 안 써도 됨 : sizeof value 또는 sizeof(value) 둘 다 가능 

 

정수형 - int

 

실수형 - float, double

데이터의 오차를 줄이기 위해 double형을 기본으로 사용하는 것이 권장됨 

long double이라는 C 표준 자료형도 존재하지만, 호환성이 떨어지므로 사용하지 않는 것이 좋다.

문자형 - char

컴퓨터는 0과 1만 인식할 수 있기 때문에 문자를 표현하기 위해서는 특정 숫자와 특정 문자를 대응시키는 코드를 사용한다.
대표적인 코드가 ASCII 코드 - 0~127 사이의 숫자에 문자를 대응
→ -128 ~ +127 범위를 표현할 수 있는 char 데이터 형으로 문자를 표현한다. 

 

문자형으로 변수를 대입하거나 초기화 할때 문자는 항상 single quote ('') 로 묶어 준다!  e.g. char ch1 = 'A' 

#include <stdio.h>
int main(void)
{
    char ch1 = 'A';
    char ch2 = 'b';
    char ch3 = '1';

    printf("%d, %c\n", ch1, ch1);  // 65, A가 출력
    printf("%d, %c\n", ch2, ch2);  // 98, b가 출력
    printf("%d, %c\n", ch3, ch3);  // 49, 1이 출력
    return 0;
}

위 코드에서 %d 로 출력할 때 ASCII 코드 값이, %c로 출력할 때 문자열이 출력되는 것을 알 수 있다!  

→  'A','b','1'과 같은 '문자형' 을 저장할 때 내부적으로는 해당 문자의 아스키코드 값이 저장된다! 

 

그래서 사실은 char도 엄밀히 말하면 정수형이다. char에 저장되는 문자가 ASCII 코드로 표현 가능한 문자라면, 정수형 int로 선언해서 ASCII코드 값을 저장한 후 %c 서식으로 출력해도 동일한 문자 값을 얻어 낼 수 있다. 다만, int와 char 둘다 정수값을 저장하지만 실제 정수의 경우는 더하기 빼기 같은 연산이 중요한 반면, 문자같은 경우는 연산이 무의미하다 ('A'+'1'를 하면 내부적으로는 65+49 = 114 가 되는데 ASCII 코드의 114는 'r'이므로 결국 'A'+'1' = 'r' 이 된다. 이 결과는 의미있는 연산이 아니다) 

→  따라서, 연산을 필요로 하는 숫자는 int형으로, 연산이 필요없는 문자는 char 형으로 저장하는 것이다! 

 

signed와 unsigned

sign 은 부호를 의미한다. 즉, signed는 '부호가 있는'을, unsigned는 '부호가 없는'을 의미한다. 정수형 기본 자료형 앞에 unsigned를 붙이면, 데이터 표현 범위에서 음수를 제거하고, 0과 양의 정수만을 표현하겠다는 의미이다. (음수를 제거하여 양수의 표현 범위를 두배로 늘리고자 하는 의도) 

unsigned를 붙이면 음수를 표현하지 않는만큼 양수를 표현할 수 있는 범위가 늘어난다.

 

상수

변수기 변하는 수라면, 상수는 변하지 않는 수이다. 변수 값이나 상수 값이나 모두 메모리에 존재하는 수이지만, 변수로 선언한 메모리에 저장된 값은 변경할 수 있지만, 상수로 선언한 경우 값을 변경할 수 없다. C언어에서 상수는 리터럴 상수와 심볼릭 상수의 두 가지로 나뉜다. 

리터럴 상수 (Literal Constans)

문자 그대로의 상수. 리터럴 상수는 변수처럼 자료형을 정하지 않고, 그냥 상수를 냅다 찍으면 컴파일러가 그 상수를 보고 알아서 적당한 크기와 자료형으로 자동으로 메모리 공간을 생성한다. 다만 상수 뒤에 접미어를 붙이면 크기를 강제로 지정할 수 있다. 

30 // 컴파일러가 자동으로 short 타입을 할당하고 2바이트를 갖게 됨 
50000 // 컴파일러가 자동으로 int형으로 할당하고 4바이트를 갖게 됨 
30L // long으로 강제 지정 -> 4바이트의 long형 상수가 됨
30U // unsigned로 강제 지정 -> 2바이트의 unsigned short 형 상수가 됨

 

💡 자료형 강제 지정 시 접미사 : U(unsigned int), L(long), UL(unsigned long), F(float), L(long double) **소문자도 가능 

 

심볼릭 상수 (Symbolic Contants)

상수를 상징하는 기호를 사용해서 상수를 나타내는 것.
변수를 '상수화'해서 선언하는 것이며, 변수를 선언할 때 앞에 const 키워드를 붙임으로서 변수를 상수화 할 수 있다. 

단, 이때는 변수 선언과 동시에 초기화 해야한다! e.g. const int TEN = 10;  

 

만약 const int TEN ; 으로 선언만 먼저 한 후 TEN = 10; 으로 초기화를 하려고 하면 에러가 발생한다. 
왜냐하면 C 언어에서는 변수를 초기화 없이 선언만 하게 되면 메모리를 할당하면서 쓰레기 값(garbage)를 채우기 때문에 const int TEN;을 한 순간 TEN이라는 변수는 쓰레기값을 가진 변수가 된다. 그런데 우리는 이를 상수로서 선언했기 때문에 더이상 값을 바꿀 수가 없는 것이므로 TEN= 10;은 에러를 발생시키게 된다. 

💡심볼릭 상수를 선언할 때 변수명은 관습적으로 대문자로 표기한다! 

 

데이터 입력

C언어에서는 scanf()를 통해 데이터를 입력받는다. printf의 f와 동일하게, scanf의 f도 formatting을 의미하기 때문에 %d와 같은 서식 문자열을 사용한다.(정확히는 서식 들어가야 한다).  e.g. scanf("정수 %d", &v)) , scanf("%d", &v))  

 

scanf()를 사용할 때는 인수로 서식과 변수의 메모리주소(&변수명 형태)를 사용한다.

정수형 변수를 입력받으려는 경우 scanf("%d", &input), 실수형 변수를 입력받는 다면 scanf("%f", &input)과 같이 사용하면 된다. 
→  입력받은 데이터가 input변수에 저장된다. 

여러 변수를 입력받을 때는  scanf("%d%d", &input1, &input2) 와 같이 사용할 수 있다.
→  입력받은 데이터가 순서대로 input1, input2 변수에 저장된다. (변수 간 구분은 스페이스바나 엔터) 

 


Reference

1. C Programming : A Modern Approach, 2/E  K. N. King | W. W. Norton & Company

2. 나혼자 C언어 이창현  | 디지털북스 | 

반응형

댓글