데이터를 저장하고 관리하는 식별자를 변수(變數: Variable)라고 합니다. 변수는 데이터 type에 맞는 값을 저장할 수 있는 공간을 가집니다. 이들 변수명은 컴파일이 끝나고 나면 변수명은 실제로 변수의 값이 저장된 메모리 정보로 바뀌게 됩니다.

 

변수의 선언은

데이터TYPE 변수명1;
데이터TYPE 변수명1 = 초기화값1;
데이터TYPE 변수명1, 변수2;
데이터TYPE 변수명1 = 초기화값2, 변수2;

와 같은 형식으로 선언을 합니다. 변수의 type 뒤에 공백문자 그리고 변수명들은 콤마(,)로 나열하면서 여러개를 동시에 선언할 수 있습니다. 각각의 변수는 초기화를 할 수 있습니다. 

 

ex).

int var1;
int var2 = 0;
int var3, var4 = 0;

변수들의 명명 규칙은 정해진 표준은 없습니다만, 명사의 단어들로 구성하면서 UNIX / LINUX 계열에서 프로그램을 개발하는 사람들은 단어와 단어 사이에 _를 붙여서 소문자로만 구성하는 것이 일반적이고, Windows 계열에서 개발을 많이 한 사람들은 헝가리언 표기법을 사용하는 경향이 있으나, 함께 개발하는 프로젝트이면 개발 표준에 따라서 진행을 하고 그렇지 않으면 편안한 대로 하면 됩니다. 단어가 긴 경우에는 약어를 사용하거나 DBMS의 column명과 같은 규칙을 사용하기도 합니다.

 

예). Unix / Linux 계열 개발자

    char user_name[20];  // 소문자 명사_명사
    long user_no;
    char birthday[9];    // 한단어는 소문자 명사

 

예). Windows 개발

    char strUserName[20];   // 앞에 데이터 type을 기술하고 단어들의 시작만 대문자 
    long lUserName;         // 
    char strBirthday[9];    // 

 


정수형 데이터 타입

정수형은 소숫점이 없는 숫자를 저장할 수 있는 데이터 type으로 char, short, int, long이 있습니다. Java 언어에서는 시스템에 관계없이 데이터의 크기(바이트 수)가 정해져 있으나, C언어는 정해져 있지 않습니다. char는 문자를 저장하는 용도로 많이 사용하기 때문에 문자형으로 부릅니다.

 

C언어에서는

char <= short <= int <= long <= long long

으로만 정의 되어 있습니다. 예를들면 "int는 short보다 같거나 클 수 있다." 정도만 정의되어 있습니다. 이를 바탕으로 OS의 bit수(즉, 64bit OS, 32bit OS 등)나 컴파일러에 따라서 크기가 다를 수 있습니다. 

 

OS의 bit수 별로 일반적인 데이터 타입별 변수의 크기입니다.

 

데이터 타입 16bit OS 32bit OS 64bit OS
char 8bit (1byte) 8bit (1byte) 8bit (1byte)
short 16bit (2bytes) 16bit (2bytes) 16bit (2bytes)
int 16bit (2bytes) 32bit (4bytes) 32bit (4bytes)
long 32bit (4bytes) 32bit (4bytes) 64bit (8bytes)
long long 32bit (4bytes) 64bit (8bytes) 64bit (8bytes)

int 타입은 보통 WORD 타입이라고 부르는 데, 이는 int 타입의 데이터 처리가 OS나 CPU에서 처리 최적화가 되어 있기 때문입니다. 그래서 몇 bit OS라고 하면 int는 그 bit수와 같은 것이 원칙이었습니다. 그러나 64bit OS가 나오면서 int가 64bit가 아닌 32bit가 되었습니다. 이유는 C언어에서 32bit 크기의 숫자를 표기할 방법이 없어져서 int를 32bit로 유지하는 것으로 합의된 것 같습니다.

 

이와 같이 타입에 따라서 데이터의 범위가 다르기 때문에 데이터의 타입의 포함관계를 표현한다면

char < short < int < long < long long < float < double < long double

와 같습니다.

 

그래서 

int  value1 = 20;
long value2 = 100;

value1 = value2;       // 오류: 큰 그릇의 것을 작은 그릇에 담으려는 오류생
value2 = value1;       // 정상: 큰 그릇에 작은 그릇의 내용물을 담을 수 있으므로 OK
value1 = (int)value2;  // 정상: 큰 그릇의 내용물 중 작은 그릇으로는 넘치는 부분은 버리고 담기

서로간의 대입관계는 위의 주석부분과 같습니다. 큰 그릇에 작은 그릇의 내용물을 담을 수 있지만, 그 반대는 불가능합니다. 만약 큰 그릇의 내용물을 작은 그릇에 반드시 담으려면 넘치는 부분은 버리고라도 담겠다고 할 경우에는 위의 value1 = (int)value2; 처럼 표현하면 됩니다. value2의 값이 100이면, value1에 당연히 담기는 데 왜 오류가 나지 생각할 수 있겠지만, compiler는 내용물의 양으로 판단하는 것이 아니라 그릇의 크기만 비교합니다.

 

 

그리고, C언어에서는 정수형 타입에 대해서는 음수와 양수를 모두 저장할 수 있는 signed 정수형와 자연수만 표현할 수 있는 unsigned 정수형이 있습니다.

 


signed 정수형

 

64bit OS 기준으로 signed 정수형 데이터의 표현 범위에 대해서 알아보겠습니다.

char      : -128 ~ 127
short     : -32,768 ~ 32,767
int       : -2,147,483,648 ~ 2,147,438,647
long      : -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807
long long : -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807

위와 같이 데이터의 범위는 음수와 양수를 모두 표현할 수 있습니다. 기본 타입 앞에 signed라는 예약어를 붙여서 표현하기도 하지만 요즘은 거의 사용하지 않고 있습니다. 

 

signed 데이터 타입은 아래와 같이 표현해도 됩니다

char
    - signed char

short
    - signed short
    - signed short int

int
   - signed int
   - signed

long
   - signed long
   - signed long int

long long
   - signed long long
   - signed long long int

즉, signed나 int는 생략이 가능합니다. (int는 둘 다 생략하면 안됩니다.)

 

 


 

예제). int 형 변수 선언

int  data1;            // 변수를 초기화 하지 않고 선언
int  data2  = 'C';     // 변수를 단일 문자 상수로 초기화
int  data3  = -3200;   // 변수를 10진수 상수로 초기화
int  data4  = 0x30;    // 변수를 16진수 상수로 초기화
int  data4  = 07126;   // 변수를 8진수 상수로 초기화
int  data6  = data2;   // 변수를 다른 변수의 값으로 초기화

 

예제). long 형 변수 선언

long data1;                       // 변수를 초기화 하지 않고 선언
long data2  = 'C';                // 변수를 단일 문자 상수로 초기화
long data3  = 1000000;            // 변수를 10진수 상수값으로 초기화
long data4  = -100000000000L;     // 변수를 10진수 long형 상수값으로 초기화
long data5  = 0x30;               // 변수를 16진수 상수값으로 초기화
long data6  = 07126;              // 변수를 8진수 상수값으로 초기화
long data7  = data2;              // 변수를 다른 변수의 값으로 초기화

 

데이터를 화면에 출력)

#include <stdio.h>

int main(int argc, char **argv)
{
    int  val = 1000;
    long val2 = 1234567890123456L;

    printf("out1 = [%d]\n", val);      // 숫자의 길이대로 출력
    printf("out2 = [%10d]\n", val);    // 10자리 폭으로 우측 정렬 출력
    printf("out3 = [%-10d]\n", val);   // 10자리 폭으로 좌측 정렬 출력
    printf("out4 = [%010d]\n", val);   // 10자리 폭으로 앞에 0으로 채워 출력
    printf("out5 = [%+d]\n", val);     // 부호를 붙여서 출력 (-는 원래 부호가 붙여서 출력됨)
    printf("out6 = [%-10d]\n", val);   // 숫자의 10자리 폭으로 좌측 정렬 출력
    printf("out7 = [%x]\n", val);      // 0x가 안붙는 16진수로 출력
    printf("out8 = [%#x]\n", val);     // 0x형식의 16진수로 출력
    printf("out9 = [%#010x]\n", val);  // 16진수를 10자리로 출력시 앞부분에 0을 채워 출력
    printf("out10= [%ld]\n", val2);    // long 데이터 출력

    return 0;
}

결과:
out1 = [1000]
out2 = [      1000]
out3 = [1000      ]
out4 = [0000001000]
out6 = [1000      ]
out7 = [3e8]
out8 = [0x3e8]
out9 = [0x000003e8]
out10= [1234567890123456]

printf( )함수는 데이터를 formating해서 화면에 출력하는 함수입니다. signed 정수값을 출력할 때에는 "%d"를 사용하고 long형 데이터는 "%ld"형태로 출력합니다. 이 함수의 상세한 사용법은 printf(3) - 데이터를 format된 형태로 화면 출력를 참고하세요.

 

 


unsigned 정수형

 

64bit OS 기준으로 unsigned 정수형 데이터의 표현 범위에 대해서 알아보겠습니다.

unsigned char      : 0 ~ 255
unsigned short     : 0 ~ 65,535
unsigned int       : 0 ~ 4,294,967,295
unsigned long      : 0 ~ 18,446,744,073,709,551,615
unsigned long long : 0 ~ 18,446,744,073,709,551,615

위와 같이 데이터의 범위는 0과 양수 즉, 자연수를 표현할 수 있습니다. 기본 타입 앞에 unsigned를 붙여서 변수를 선언합니다. 

 

unsigned 데이터 타입은 아래와 같이 표현해도 됩니다

unsigned char

unsigned short
    - unsigned short int

unsigned int
   - unsigned

unsigned long
   - unsigned long int

unsigned long long
   - unsigned long long int

unsigned는 생략이 불가하며, int는 생략이 가능합니다. 

 

 

변수 선언 예제)

unsigned int  data1;                     // 변수를 초기화 하지 않고 선언
unsigned      data2  = 20000;            // 변수를 단일 문자 상수로 초기화
unsigned long data3  = 10000000000000UL; // 변수를 10진수 상수값으로 초기화
unsigned long data4  = data3;            // 변수를 다른 변수의 값으로 초기화

......

printf("data2 = [%u]\n",  data2);
printf("data3 = [%lu]\n", data3);

결과)
data2 = [20000]
data3 = [10000000000000]

unsigned 정수형의 데이터 출력 format은 "%u"이며, long형은 "%lu"로  지정하면 됩니다.

 

 


정수형 상수 (常數: constant number)

상수는 변수의 반대적 개념으로 값을 변경할 수 없다는 의미입니다. 상수의 종류로는 선언/사용하는 방식에 따라 이름이 있는 상수, macro 상수, literal 상수로 구분할 수 있습니다. 

 

1. literal 상수

literal 상수는 숫자 자체를 의미합니다.  1000, -1200 등과 같이 숫자 자체를 표현하는 것을 정수형 literal 상수라고 합니다.

10진수로 표기
   10000
   1234
   -12346

16진수로 표기 (0x 또는 0X가 앞에 붙음)
   0xa010
   0XA0B0

8진수 표기 (0이 앞에 붙음)
   07021

long 데이터 표기 (끝에 L 붙임)
   1000000000000000L

unsigned 데이터 표기 (끝에 U붙임)
   100000U
   
unsigned long 데이터 표기 (끝에 UL 붙임)
   1000000000UL

 


 

2. 이름 있는 상수

const 데이터타입 상수이름 = 초기화값;

형태로 선언하며, 변수를 선언하는 방법과 같으며 앞에 const만 붙이면 됩니다. 명명 규칙상 상수의 이름은 대문자로만 구성하는 것이 일반적입니다. (소문자로 구성해도 상관은 없으나 변수와 구분하기 위해서 대문자로 사용하는 것이 일반적입니다.)

 

ex).

const int   MAX_VALUE = 10000;
const long  MAX_SIZE  = 2000000000000L;

위와 같이 선언합니다.

 

const int   MAX_VALUE = 10000;

MAX_VALUE = 2000;

처럼 상수의 값을 변경하려고 하면 오류가 발생합니다. 즉, 상수는 초기화된 값을 변경할 수 없습니다.

 


3. 매크로 상수

매크로 상수는 #define을 이용하여 prepressor가 치환해주는 역할을 하는 상수입니다.

#define 매크로명  상수값

끝에 세미콜론(;)을 붙이지 않습니다.

#define MAX_VALUE 1000000

처럼 사용하며 데이터 type이 없으므로 컴파일러는 타입체크를 값으로 합니다.

 

 

ex).

#define MAX_VALUE 1000000

...

int value = MAX_VALUE;

라고 사용하면 preprocessor가 컴파일 시에 

int value = 1000000;

로 데이터를 치환한 후에 컴파일이 됩니다. 즉 MAX_VALUE라는 이름이 없어지고 literal 상수화 되어버립니다. 

 


#define으로 선언하는 매크로 상수와 const로 선언하는 이름이 있는 상수는 원칙적으로 const를 사용하는 것이 좋습니다. const를 사용하면 별도의 데이터 타입을 명확하게 할 수 있어서 컴파일러가 인식하기에 좋습니다.

그러나, 시기적으로 매크로 상수는 C언어의 초창기부터 제공된 기능으로 아직도 많은 개발자들은 매크로 상수를 많이 사용하고 있습니다. 

 

 

 

C Programming Language 문법

1. C 프로그래밍 언어는? 2. C언어 개발 환경 (실습 환경) 3. C언어의 컴파일 과정 4. C 소스 파일 구성 5. 주석문(Comment) 6. 식별자 명명 규칙 7. C 프로그래밍의 시작 - 함수 8. 변수와 상수 (정수형) 9. 변..

www.it-note.kr

 

'C언어 > 문법' 카테고리의 다른 글

10. 변수와 상수 (문자, 문자열)  (0) 2019.10.28
9. 변수와 상수 (실수형)  (0) 2019.10.24
8. 변수와 상수 (정수형)  (0) 2019.10.23
7. C 프로그래밍의 시작 - 함수  (2) 2019.10.22
6. 식별자 명명 규칙  (2) 2019.10.22
5. 주석문(Comment)  (0) 2019.10.22
블로그 이미지

사용자 자연&사람

행복한 개발자 programmer since 1995.

Tag ,

댓글을 달아 주세요