About C – “리터럴, 변수, const, 자료형, 열거형, typedef”
About C – “리터럴, 변수, const, 자료형, 열거형, typedef”
식별자란?
프로그래밍을 하다 보면 여러가지 변수를 선언해야 할 수도 있고, 함수를 선언해야 할 때도 있습니다. 예를 들어 int x; 라고 int형 변수 x를 선언했다고 가정합시다. 우리가 이름 붙인 x처럼, 식별자란 변수나 함수 등에 부여하는 이름을 말합니다.
식별자를 이름붙이는 데에는 몇 가지 규칙이 존재합니다.
- 영문자, 숫자, 언더바(_)만 사용할 수 있습니다.
- 한글이나 언더바(_)을 제외한 특수문자는 사용할 수 없습니다.
- 첫 번째 글자는 반드시 영문자 또는 언더바(_)로 시작해야 합니다.
- 언더바(_)는 첫 글자로도 사용할 수 있지만, 이미 만들어진 식별자들이 밑줄로 시작하는 경우가 많으므로 사용하지 않는 것이 좋습니다.
- 예약어는 식별자로 사용할 수 없습니다.* C언어는 대문자와 소문자를 구분합니다.
리터럴이란?
영문자 literal은 “문자 그대로”라는 뜻입니다. 리터럴은 실행 중 그 값이 변하지 않는 상수를 의미합니다.
- 정수형 리터럴은 0을 포함한 소수점이 없는 수를 의미합니다.
- 부동소수점형 리터럴은 부동 소수형 그 자체를 의미합니다.
- 문자형 리터럴은 1byte의 문자를 의미합니다.
- 문자열 리터럴은 두 개 이상의 문자 묶음을 의미합니다.
리터럴과 상수의 차이
상수는 변수의 상대적 의미이고, 심볼 또는 식별자를 의미합니다.리터럴은 값 그 자체로, 고정된 값을 표현하는 것을 의미합니다.
- 144, 56234, “HI~” 등은 리터럴입니다.
- int x = 9; 에서, x는 변수를 의미하고, 7은 리터럴입니다.
- const int b = 99에서, b는 상수를 의미하고, 99는 리터럴을 의미합니다.__(const는 상수를 선언한다는 의미입니다. 조금 있다 다뤄 보겠습니다. 일단은 b가 상수를 의미한다는 것만 알면 됩니다.)
정수 리터럴
- 정수 리터럴은 10/8/16진수의 상수가 될 수 있습니다.
- 10진 정수 리터럴은 우리가 일상적으로 접하는 상수, 예컨대 111, 12, 2, 5 등입니다.
- 8진 정수 리터럴은 0에서 7까지만 사용하는 8진수로 구성된 수로, 8진수라는 것을 나타내기 위해서 0234, 0577처럼 앞에 ‘0’을 붙입니다.
- 16진 정수 리터럴은 10진수 10에서 15에 해당하는 수를 표현하기 위해서 A부터 F까지의 영문자를 사용합니다. 16진 숫자 앞에는 ‘0X’ 나 ‘0x”를 씁니다. 소문자 x를 사용할 때에는 a-f를, 대문자 X를 사용할 때에는 A-F를 사용합니다.
- long형 상수의 경우에는 숫자 뒤에 L 혹은 l을 더 붙여 사용합니다. ex) 10진 long형 리터럴 : 10L, 16진 상수 리터럴 : 0XFFL
실수 리터럴
- 실수 리터럴은 부동 소수점형 상수를 의미합니다.소수점을 포함하는 수이므로 당연하게도 정수형보다 더 크고 작은 수를 정확하게 표현할 수 있겠습니다.
- 십진형 은 정수부,소수점,소수부로 구성됩니다. 123.5, 1.566, -0,523 처럼 말입니다.
- 소수점 앞 뒤에 0만 있다면 0은 생략이 가능합니다. 예컨대 100.0은 100. 으로 표현할 수 있고, -0.312는 -.312로 표현할 수 있습니다.
- 지수형의 소수부는 10진수로, 지수부는 e나 E로, 부호, 지수로 구성됩니다. 예컨대 0.33335e+9는 0.33335*10^9를 의미합니다.
- 지수는 정수형만 사용하고, 부호를 생략한다면 양수로 가정합니다. 예를 들면 0.634e03은 0.634*10^3을, -3.4545e-66은 -3.4545*10^(-66)을 의미합니다.
문자형 리터럴
- 문자형 리터럴은 character의 줄임 char형이라고 합니다.
- 1바이트의 메모리에 저장됩니다.
- 실제 메모리에 저장될 때는 ACCII 코드 값으로 저장됩니다.
- ‘작은 따옴표’로 묶어 사용해야 합니다. ‘7’은 연산이 불가능한 문자 7으로, 숫자 7과는 다릅니다.
- ‘\n’, ‘\0’ 등은 이스케이프 시퀀스로, 두 개의 문자로 보이지만 두 개의 문자가 하나의 의미를 갖는 문자 상수입니다.
아래의 코드를 살펴보면, 알 수 있을 것입니다.
#include <stdio.h>
int main(void)
{
printf("%c \n",'a'); //%c는 문자로 출력합니다. a
printf("%d \n",'a'); //%d는 숫자로 출력합니다. a의 ASCII코드값 97이 나옵니다.
printf("%d \n",7); //%d는 숫자로 출력합니다.
printf("%c \n",'7'); //윗줄과는 다르게 ''로 둘러쌓여 있습니다. %c는 문자로 출력합니다. '문자' 7이 나올 것입니다.
printf("%d \n",'7'); //문자 리터럴 을 숫자로 출력하면 7의 ASCII 코드 값 55가 나올 것입니다.
return 0;
}
아래는 영문자 X와 x의 ASCII 코드 값을 출력하는 예제입니다.문자 리터럴 X와 x를 %d(10진 숫자)로 출력하면 ASCII코드 값이 출력됩니다.
#include <stdio.h>
int main(void)
{
printf("X=%d, x=%d\n", 'X' , 'x' );
return 0;
}
문자열 리터럴
- 여러 개의 문자 모임을 나타냅니다.
- 2개(한글은 한 개) 이상의 문자를 나타냅니다.
- 문자형과는 다르게 “” 큰 따옴표로 묶어 사용해야 합니다.
- 각 문자가 한 바이트씩 저장됩니다.
- 예를 들어, 문자열 리터럴 “ABCD”는 각각 2진수로 메모리에 저장됩니다.
- 문자열 리터럴에서는 문자열의 끝을 의미하는 NULL문자가 제일 뒤에 자동적으로 붙여집니다.
#include <stdio.h>
int main(void)
{
printf("%c, %s\n",'X',"X");
return 0;
}
문자형 X와 문자열 X는 다릅니다. 문자열 리터럴 “X”에서는 NULL 문자가 자동으로 붙어서 2바이트에 저장됩니다. 예제를 직접 실행해 보세요.
변수 선언문, 변수를 상수화하기
자료를 저장하도록 할당된 기억장소의 이름을 변수라고 합니다. 모든 변수는 사용하기 전에 선언을 해야 합니다. 선언의 방법은 다음과 같습니다.
자료형 변수명;
의 방법으로 선언합니다.int x;
int형 변수인 x를 선언double average;
double형 변수인 average를 선언int x, int y, int z;
동일한 자료형을 가지는 두 개 이상의 변수는, (,)로 서로를 구분하여 한번에 선언- 같은 방법으로,
float math, sci, kor;
과 같이 선언도 가능합니다.
변수를 선언하면서 초기화할 수도 있습니다.
int age = 5;
int형 age를 선언하고 5를 대입했습니다.double A = 1.4, B = 5.3
처럼 여러개의 변수를 한번에 선언하고 초기화 할 수도 있습니다.
const 키워드를 사용하면 변수를 상수화할 수 있습니다. ‘const 변수선언문’ 으로 사용합니다.
const int x = 5;
를 하면 이제 x의 값은 변경할 수 없습니다.
이미 값이 할당된 상수에 다른 값을 대입하려 하면 오류가 발생합니다.
#include <stdio.h>
int main()
{
const int x = 5;
x = 10;
return 0;
}
main.c:6:4: error: cannot assign to variable ‘x’ with const-qualified type ‘const int’ – 상수화된 변수 x에 10을 할당할 수 없습니다.
#include <stdio.h>
int main(void)
{
num = 5;
printf("%d",num);
int num; //num을 선언하기 전 5라는 값을 대입하였으므로 에러가 납니다.
return 0;
}
>C99부터는 실행문 다음에 선언문이 올 수도 있습니다.예를 들어, 아래의 코드는 C99를 지원하는 컴파일러에서는 오류를 발생시키지 않습니다.
int main(void)
{
int num; // 선언문
num = 5; // 실행문
int num2; // num = 5;라는 실행문 다음 선언문이 옴
num2 = 10;
return 0;
}
C99부터는, 그리고 C++에서도 실행문 다음에 선언문이 올 수 있습니다.오해하면 안 될 것이,
int main(void)
{
num = 5; // 실행문
int num;
return 0;
}
이런 식으로 선언하지 않고 사용하면 C99 이상에서도 오류가 발생합니다.필요한 선언문을 모두 써 놓고 – 실행문을 작성하라는 것이지, 선언하지 않고 실행문을 작성하라는 것으로 오해하면 안 되겠습니다.
자료형의 종류
- 문자형, 정수형, 부동형, 열거형을 기본 자료형 이라고 부릅니다.
- 배열, 함수, 구조체, 공용체, 포인터를 유도 자료형 이라고 부릅니다.
- void 형은 값이 없음을 표시하는 자료형입니다.
- 가장 많이 사용하는 대표적인 기본 자료형은 문자형, 정수형, 실수형입니다.
기본 자료형의 종류 – 문자형
- 문자 하나를 저장하기 위한 형입니다.
- 1바이트의 메모리가 할당됩니다.
- 실제 기억장소에 기억될 때는 해당 ASCII코드 값이 저장됩니다.
- 문자 리터럴을 쓸 때는 반드시 양쪽에 작은 따옴표”를 사용합니다.
- 한글은 한 글자가 2바이트가 되어, 한 글자라도 문자형이 될 수 없습니다.
- unsigned가 추가로 붙은 형은 부호가 없는 형으로, 있는 형에 비해 2배 크기의 수까지 저장할 수 있습니다.
- char형은 signed가 생략된 부호가 있는 형입니다.
기본 자료형의 종류 – 정수형
- int 형 : -(2^31)-1 ~ (2^31) -1 까지의 소수점이 없는 정수를 저장할 수 있습니다.
- unsigned int 형 : 0 ~ (2^32)-1 까지의 소수점이 없는 정수를 저장할 수 있습니다.
- int형의 크기는 플랫폼이나 컴파일러에 따라 달라집니다.
- 예컨대 16비트 DOS상에서 동작하는 오래된 컴파일러에서의 int형은 16비트입니다.
- C99에서 추가된 정수형에 대하여 소개합니다.
- long long int형 – 최소 8바이트로 규정되어 있습니다.
- _Bool형 – boolean형으로, 0이나 1만을 저장하는 부호없는 정수형입니다.
- 0이 아닌 다른 값은 모두 1로 바뀌어 저장됩니다.
#include <stdio.h>
int main(void)
{
_Bool b1, b2, b3;
b1 = 0;
b2 = 1;
b3 = 4; //b3에 4를 대입하였지만, 0이 아닌 값은 모두 1로 바뀌어 저장됩니다.
printf("b1 = %d \nb2 = %d \nb3 = %d\n", b1, b2, b3);
//b1 = 0, b2 = 1, b3 =1으로 출력됩니다.
return 0;
}
헤더 파일을 이용해서, 조금 더 편하게 사용할 수도 있습니다. <stdbool.h>
에서는, _Bool을 bool으로, true를 1로, false를 0으로 정의하고 있습니다.
#include <stdio.h>
#include <stdbool.h>
int main(void)
{
bool bl1, bl2;
bl1 = false;
bl2 = true;
printf("bl1 = %d\nbl2 = %d\n", bl1, bl2);
}
bl1을 false로, bl2를 true로 정의했지만, 화면에는 bl1 = 0, bl2 = 1로 출력되는 것을 확인할 수 있습니다.
기본 자료형의 종류 – 실수형
- float형 , double형, long double형이 있습니다.
#include <stdio.h>
int main()
{
float num1 = 0.0f;
double num2 = 0.0;
long double num3 = 0.0l; // online c compiler에서는 16이 나옴
printf
(
"float: %ld, double: %ld, long double: %ld\n",
sizeof(num1),sizeof(num2),sizeof(num3)
);
return 0;
}
- 다른 개발환경, 컴파일러에서 실행해 보면 각각의 크기가 다른 것을 확인할 수 있습니다.
- C언어의 자료형은 크기가 정해져 있지 않습니다. long은 int보다 크거나 같다라는 방식으로 표준에 정의되어 있습니다. sizeof() 함수를 이용해, 크기를 확인하시는 것을 추천드립니다.
- 대부분의 컴파일러는 현재 char을 1바이트, short를 2바이트, int와 long을 4바이트, double 을 8바이트로 구현합니다.
자동 형 변환
- 자료형이 서로 다른 혼합 연산에서는 기억 장소의 크기가 큰 쪽으로 통일시켜 연산이 이루어집니다.
- 예를 들어, char형과 int형이 연산되려면, 크기가 작은 char형이 int형으로 형변환되어 연산되고 결과 또한 int형으로 나옵니다.
#include <stdio.h>
int main()
{
int x = 5;
char y = 'h';
printf("현재 컴파일러에서, int형 크기: %lu\n현재 컴파일러에서, char형 크기: %lu\n",sizeof(x), sizeof(y));
printf("y가 int형으로 형변환되면, %d\n",y);
printf("x는 이미 5이므로, 둘을 더하면\n");
printf("x+y = %d", x+y);
}
//sizeof()로 x와 y의 형의 크기를 알아보았습니다.
//char형인 y의 'h'가 int형으로 형변환이 되면, 104입니다.
//고로, 5 + 'h' = 109가 됩니다.
열거형 – ENUM
- 열거(enumerated)형은 enum이라고 표현하며 나열된 데이터들에 일정한 값을 부여합니다.
- 열거된 데이터에는 정수 값 을 대응시킵니다.
enum 열거형명{데이터1,데이터2,,,};
로 사용합니다.
enum names{smith, james, yamamoto, gyun};
- 에서, names가 열거형명이고 중괄호에 나열된 데이터의 목록에 대해 0부터 1씩 증가된 값이 자동 할당됩니다.
#include <stdio.h>
int main() {
enum names{smith, james, yamamoto, gyun};
printf("%d\n%d\n%d\n%d\n",smith,james,yamamoto,gyun);
}
- 0부터 3까지의 정수가 나오는 것을 볼 수 있습니다.
- 열거형명으로 데이터들을 대입하는 것이 아니라, 열거형 변수를 만들어 사용합니다. enum days 형 변수를 만드는 것입니다.
#include <stdio.h>
int main() {
enum names{smith, james, yamamoto, gyun} myname;
//윗 줄처럼 {}이후에 쓸 수 있습니다.
enum names yourname; // 이러한 방식으로도 선언 가능합니다.
enum names yourname2 = gyun; // 할당된 숫자 3
myname = james; // 할당된 숫자 1
yourname = smith; //할당된 숫자 0
printf("myname = %d\nyourname = %d\nyourname2 = %d\n", myname, yourname,yourname2);
}
- 특정한 값이 대입되면 그 값에서 1씩 증가하여 할당됩니다.
#include <stdio.h>
int main() {
enum names{smith, james, yamamoto = 5, gyun, yong};
enum names myname = smith; // 0
enum names yourname = james; // 1
enum names yourname2 = yamamoto; // 5
enum names yourname3 = gyun; // 6
printf("smith = %d, james = %d, yamamoto = %d, gyun = %d",myname, yourname, yourname2, yourname3);
return 0;
}
위의 예제를 실행해 보세요.
결론적으로, 열거형을 사용하면 정수형 수를 이용하여 대입하는 것보다 의미 있는 단어를 직접 대입하므로, 프로그램을 해석하기가 쉬워지는 것입니다.
기존 자료형을 새로운 형으로, TYPEDEF
- 기존 자료형을 새로운 형으로 선언합니다.
typedef 기존형 새로운형이름;
으로 사용합니다.typedef int jungsu;
int형과 똑같은 jungsu라는 자료형을 만들었습니다.- 고로,
int a = 5
라는 선언문과jungsu a = 5;
라는 선언문은 같습니다.
#include <stdio.h>
int main()
{
typedef int jungsu;
int a = 5;
jungsu b = 1000;
printf("a = %d\n", a);
printf("b = %f\n", b);
}
와 같이 실행하여 확인할 수 있습니다. 경고 메시지에,
format specifies type
'double' but the argument has type
'jungsu' (aka 'int') [-Wformat]
라고 뜨는 것이지요. printf 로 jungsu 를 출력할 때 double형을 사용하는 %f를 썼지만, jungsu형은 int형과 같으므로 %d를 써야 한다고 알려주는 경고 메시지입니다.
이렇게 하여 C 언어 문법 리터럴, 변수, const, 자료형, 열거형, typedef에 대하여 알아보았습니다. 다음 시간에는, 표준 입출력 함수 등에 관하여 이야기해 볼 예정입니다. 고생하셨습니다!