C 프로그래밍 입문/문자형 데이터
문자형 데이터
[+/-]C 에는 문자를 저장하기 위한 타입은 없다. char과 unsigned char 라는 타입이 있기는 하지만, 실제 이 타입은 8비트 정수형 데이터 타입이다. 기본적으로 컴퓨터 에게는 '문자'라는 개념 자체가 없다. 단지 인간이 문자가 익숙하기 때문에 A 는 1 B 는 2 라는 식으로 문자와 숫자를 1:1로 변환해서 저장해 놓고, 나중에 출력할 때 다시 1을 A로 2를 B로 바꾸어 화면이나 프린터에 찍어주는 것 뿐이다. 이렇게 사람이 인식할 수 있는 문자를 숫자로 변환해서 저장하는 것을 문자 인코딩이라 한다. 가장 기본적인 인코딩 방식은 ASCII으로 영문자 대소문자와 숫자, 그리고 특수문자들로 구성되어있다. 기본적으로 C에서 제공되는 char 타입은 이 ASCII 문자를 저장하는 것으로 간주되는 것이 일반적이다. 알파벳을 사용하지 않는 문자들을 위해 사용되는 문자형 데이터 타입은 wchar_t로 char 타입과는 달리 한 바이트가 아닌 여러바이트(multibyte) 정수형 데이터 이다. wchar_t 타입의 문자코드는 로케일의 영향을 받아 현재 로케일에 해당되는 데이터를 저장할 수 있도록 되어있다. 다음은 C에서 제공하는 문자와 관련된 기본타입과 추가 타입이다.
타입 | 바이트수 | 최소값/최대값 | limits.h 상수 | 접미사 | 비고 |
---|---|---|---|---|---|
char unsigned char |
1 | -128 - 127 0 - 255 |
SCHAR_MIN, SCHAR_MAX UCHAR_MAX |
||
wchar_t |
wchar_t는 <stddef.h>에 정의되어 있는 정수형 타입이다. 이 타입의 변수에는 멀티 바이트 문자 한 글자가 저장될 수 있다.
문자형 상수는 홑 따옴표(' - single quotation)를 사용해서 지정 하도록 되어 있다. 다음은 문자변수에 문자 A 를 저장하는 프로그램이다. 프로그램을 실행시켜 보고 각각의 라인이 어떤 의미가 있는지 생각해 보기 바란다.
#include <stdio.h>
int main (int argc, char * argv[])
{
char achar = 'A';
printf("The character is: %c\n", achar);
printf("ASCII code of the character: %d\n", achar);
printf("A character next the character: %c\n", achar + 1);
for(achar = 'A'; achar <= 'Z'; achar++)
{
printf("%c", achar);
}
printf("\n");
}
문자열 상수는 겹 따옴표(" - double quotation)을 사용해서 지정하도록 되어있다. 주의할점은 C에는 '문자열 타입'은 없다. 실제로 문자열을 메모리에 저장하는 방법에 대해서는 나중에 다시 설명을 하게 될 것이다. '문자열 타입'의 변수가 존재하지 않기 때문에 문자열은 변수에 바로 대입할 수 는 없다. 다음 프로그램은 가장 처음 만들었던 바로 그 프로그램이다. 프로그램내에 있는 "Hello World!\n"가 바로 문자열 상수 이다.
#include<stdio.h>
int main(int argc, char * argv[])
{
printf("Hello World!\n");
return 0;
}
'A'와 "A"는 언뜻 보기엔 같아 보인다. 그리고 C가 아닌 다른 프로그래밍 언어에서는 같은 의미로 쓰이기도 한다. 그러나 C에서는 두 상수의 의미가 완전히 다른데 'A'는 A 한 바이트 데이터를 의미 하지만 "A"는 실제로 한 바이트가 더 있어 두 바이트 이다. C에서는 문자열의 길이를 따로 관리하지 않고 문자열의 끝을 표시하는 방법을 사용하는데 "A"라는 문자열의 제일 마지막에는 문자열을 표시하는 문자가 숨어있다. 문자열의 끝을 표시하는 문자는 \0으로 실제 "A"는 문자 A와 문자열 끝을 나타내는 문자 \0 두개의 문자가 합쳐진 상수 이다.
C에서 문자 상수와 문자열 상수를 표기할 때 아스키 코드를 직접 지정할 수 도 있는데 다음 네 코드는 결과적으로는 같은 동작을 하는 것이다.
#include<stdio.h>
int main(int argc, char * argv[])
{
unsigned char a = 'A';
unsigned char b = 65; /* 아스키 코드를 직접 할당 */
unsigned char c = 0x41; /* 16진수 아스키 코드로 할당 */
unsigned char d = '\x41'; /* 16진수 아스키 문자로 할당 */
unsigned char e = 0101; /* 8진수 아스키 코드로 할당 */
unsigned char f = '\101'; /* 8진수 아스키 문자로 할당 */
return 0;
}
16진수 아스키 문자는 보통 문자열 안에 여러개의 문자를 할당하려는 목적으로 사용한다. 16진수 아스키 문자를 사용할 때 주의할 점은, x다음에 오는 문자는 반드시 두 자 이어야 한다는 것이다. 사용자가 2바이트 문자코드를 사용하고자 하는 경우 "\x1234"라고 하면 될 것으로 생각하기 쉬운데 실제 C컴파일러는 '\x12'라는 문자와 '3' 그리고 문자 '4'라고 인식하게 되므로 2 바이트 문자 코드를 사용하려고 할땐 반드시 "\x12\x34"와 같이 한 바이트씩 잘라서 표기해 주어야 한다. 오해하기 쉬운 것은 '\123'으로 할당하는 경우에 10진수 123에 해당되는 아스키 문자가 할당될 것으로 생각하는 경우가 많은데, 실제로는 10진수 아스키 코드를 아스키문자로 할당할 수 는 없다. 8진수 문자를 사용하는 경우역시 마찬가지 이다. 8진수 문자는 최대 3자리 일 수 밖에 없기 때문에 "\0123"라는 식으로 써주면 8진수 표기법에 의해 아스키 코드 0123 번이 할당될 것으로 이해되기 쉽지만, 실제로는 '\012'라는 문자와 문자 '3'이 조합된 것으로 인식된다.
wchar_t 타입의 문자 변수에 값을 할당 할때는 wchar_t z = L'\x0041'와 같이 접두사 L을 달아주고, 2바이트 데이터를 그대로 사용하여 할당한다.
주석 및 참고자료
[+/-]