C언어에는 변수 선언과 관련된 많은 예약어(keyword, reserved word들이 있습니다. 많은 개발자들이 많이 사용하는 예약어는 그 의미를 잘 이해하는 데, 가끔 이런 예약어도 있었어?라고 생각하는 것들도 있습니다. 변수 선언과 관련된 모든 예약어를 다시 한번 정리하도록 하겠습니다.
변수 type 예약어
유형 | 예약어 | 비고 |
문자형 | char | 1바이트의 문자를 표현하는 타입, 정수형으로 사용가능 |
정수형 | short | |
int | ||
long | ||
long long | ||
signed | 문자형, 정수형의 앞에 붙어서 음수도 표현가능 타입으로 지정 (생략가능) | |
unsigned | 문자형, 정수형의 앞에 붙어서 자연수를 표현할 수 있는 타입으로 지정 | |
실수형 | float | 4 바이트의 실수 표현 |
double | 8 바이트의 실수 표현 | |
long double | double 이상의 실수 표현 | |
기타 | void | 데이터 타입이 없음 표시 (주로, 함수의 return이나 파라미터에 사용) |
void * | 타입 미정의 데이터 type |
type간 대입 관계
char < short < int < long < long long < float < double < long double
int ivalue = 2000;
long lvalue;
...
lvalue = ivalue;
작은 범위의 데이터는 큰 범위의 변수에 대입을 하면 암묵적으로 자동으로 타입변환이 일어납니다.
큰 범위의 변수를 작은 범위의 변수에 대입을 하면 오류가 발생합니다.
int ivalue;
long lvalue = 2000;
...
ivalue = lvalue; // 오류 발생
위와 같이 2000이라는 숫자는 ivalue에 저장될 수 있는 데이터임에도 불구하고 lvalue는 ivalue에 대입할 수 없습니다.
int ivalue;
long lvalue = 2000;
...
ivalue = (int)lvalue; // long 저장 공간에서 int 저장공간 크기를 벗어나는 데이터는 버리고 대입
위와 같이 명시적으로 타입변환(type casting)을 해주어야 합니다.
변수 범위 지정자
예약어 | 비고 |
auto | 함수 내에 선언하는 local 변수 (stack 변수) 지정자. 생략가능하여 거의 사용하지 않음 |
미지정 | 변수의 type 앞에 아무것도 붙이지 않으면 1. 함수 내에서 선언한 변수 - local 변수로 지정되며, stack 영역에 저장되는 변수입니다. - 함수가 호출될 때에 생성되었다가 호출이 끝나면 사라지는 변수입니다. 2. 함수 바깥에 선언한 변수 - global 변수라고 합니다. - 프로그램 실행과 동시 생성되어 전역(global) 데이터 영역에 저장됩니다. |
static | 1. 전역변수 앞에 static이 붙은 경우 - 이 전역변수는 다른 소스에서 사용할 수 없고 오로지 현재 소스 파일 내에서만 유효하다는 의미입니다. 2. local 변수 앞에 static이 붙은 경우 - 사용범위는 local이지만 이 변수는 프로그램이 실행과 동시에 생성되어 전역 데이터 영역에 저장됩니다. |
extern | 다른 소스 파일에 이 변수가 global 변수로 선언되어 있으므로 그냥 이용만 하라는 의미입니다. 따라서 extern 변수는 다른 어딘가에 extern이 붙지 않은 전역변수가 선언되어 있으므로 프로그램 컴파일(링크)시 그 파일이 함께 링킹이 되어야 합니다. |
extern의 예)
extern int total_count;
이 total_count는 다른 소스 파일에 변수가 선언되어 있다는 의미이며 초기화를 할 수 없습니다. (컴파일러는 일반적으로 warning을 발생시키고 초기화 되지 않음)
최적화 지정자
예약어 | 비고 |
register | 자주 호출되는 정수형 변수에 대해서 CPU에 있는 register중 사용하지 않는 것이 있으면, 그 register에 계속 머물면서 CPU와 일반 메모리간에 데이터 이동을 줄여달라는 의미입니다. 즉, register에 머물 수 있으면 머물면서 주메모리에 쓰기를 하지말고 성능에만 신경써라는 의미입니다. 주로 for문에서 증감 변수를 지정합니다. 그러나 요즘은 컴파일러가 최적화를 하면서 register를 붙이지 않아도 알아서 하는 경우가 있습니다. |
volatile | register의 반대 개념으로 최적화를 하지말라는 예약어입니다. 즉, register에서 한번의 연산이 일어나서 값이 변경되면 주메모리에 반드시 옮겨쓰라는 의이밉니다. register를 붙이지 않아도 컴파일러가 최적화를 하여 성능 향상을 하는 경향이 있는 데, 이를 못하게 합니다. 주로 Multi-thread환경에서 A라는 변수의 값의 변화면 다른 thread가 그 값을 판단으로 실행하고 그렇지 않으면 대기하는 로직이 있을 경우에 실제로 변수의 값이 register에 계속 loading되어 있으면, 다른 thread는 주메모리에 저장된 변수를 계속 모니터링해서 변경을 인지 못하여 실행이 안되는 경우가 발생합니다. 이와 같은 경우를 방지하기 위해서는 반드시 volatile 예약어를 변수앞에 붙이도록 합니다. |
변수의 초기화 vs. 대입의 차이
변수의 초기화하는 것과 변수만 선언하고 다음 줄에 바로 대입을 하는 것이랑 같은 의미일까요? 아래의 예제처럼 보면 결과적으로는 같은 것처럼 보입니다만, 완전히 다른 의미입니다.
예제)
long value1 = 1000; // 초기화
long value2;
value2 = 1000; // 데이터 대입
변수의 초기화는 변수가 생성될 때에 최초에 한 번만 처리되는 과정입니다. 그러나 변수의 대입은 여러번 일어 날 수 있는 일입니다. 특히, 전역변수나 static local 변수에서는 확연히 다름을 확인할 수 있습니다.
초기화 예제)
#include <stdio.h>
int func(void)
{
static long value = 10000;
value++;
printf("value = %ld\n", value);
}
int main(int argc, char **argv)
{
func();
func();
func();
return 0;
}
실행 결과
-------------------------------------------------
value = 10001
value = 10002
value = 10003
초기화는 변수가 생성될 때에 일어나며, static 변수나 global 변수는 프로그램이 실행되자마자 1회만 생성되는 변수입니다. 따라서 위와 같이 여러번 호출하더라도 1회만 생성되기 때문에 함수를 여러번 호출되어도 변경된 값이 그대로 유지됩니다.
대입의 예제)
#include <stdio.h>
int func(void)
{
static long value;
value = 10000;
value++;
printf("value = %ld\n", value);
}
int main(int argc, char **argv)
{
func();
func();
func();
return 0;
}
실행 결과
-------------------------------------------------
value = 10001
value = 10001
value = 10001
대입의 경우는 변수가 최초 생성된 후에 대입로직은 지속적으로 호출되기 때문에 계속 같은 값으로 되돌아 오게 됩니다.
'C언어 > 문법' 카테고리의 다른 글
13. 조건문 (if ~ else if ~ else) (0) | 2019.10.31 |
---|---|
12. C언어의 연산자(operator) (2) | 2019.10.31 |
10. 변수와 상수 (문자, 문자열) (0) | 2019.10.28 |
9. 변수와 상수 (실수형) (0) | 2019.10.24 |
8. 변수와 상수 (정수형) (0) | 2019.10.23 |