[C언어] 문자열(string) , 문자열상수, 리터럴(literal)
COM2008. 6. 29. 19:01 |문자열 (string)
문자열은 char 형 1차원 배열이다. ( char형의 크기는 1byte 이다. )
문자열은 NULL 문자로 그 끝을 나타낸다.
NULL 문자는 1byte의 모든 비트, 즉 8비트가 모두 0 값이다. 즉, 0000 0000
escape 문자를 사용한 NULL 문자 기호는 \0 이다.
------------------------------------------------------------------------------------------------
문자열 상수 (string constant)
문자열상수는 " " 를 사용하여 나타낸다. 단일 문자는 ' ' 를 사용한다.
문자열이 겉보기에 단일문자만 가지고 있더라도 NULL 문자때문에 단일문자와는 다르다.
문자열의 크기에는 널문자가 포함된다.
예. "abc" <-- 크기가 4바이트인 문자열 상수
연속된 문자열 상수는 접합된다. (concatenation) , 이때 문자열 상수 사이의 공백은 무시된다.
즉, "abc" "def" 는 "abcdef" 가 된다.
문자열이 길어서 중간에 끊기는 것 때문에 인쇄문을 두번 쳐야 할때, 위의 테크닉을 이용하면 편리하다. 즉, 긴문자열을 여러개로 끊고 연속시키는 것이다.
예.
printf("This string is too much "
"long. So I split the string "
"to four segments then "
"it will be concatenated.");
--------------------------------------------------------------------------------------------------
문자열 상수의 특정위치 문자 역참조하기
문자열상수는 비록 이름은 없지만, 메모리 어딘가에 저장되고, 평가값이 그 시작주소 이므로, [] 연산자를 이용해 역참조하면, 문자열의 특정위치에 있는 문자를 택할수 있다.
즉, "ABCDEFG"[4] 와 같은 꼴로 쓰면 된다. "ABCDEDFG"[4] 는 'E' 이다.
앞에서 연속된 문자열 상수가 접합된다고 하였으므로, "AB""CDEFG"[4] 라고 해도 똑같다.
예.
#include<stdio.h>
int main(void){
int i;
for(i=0;("This is a string"" literal"[i])!='\0';i++){
putchar("This is"" a string literal"[i]);
}
return 0;
}
-----------------------------------------------------------------------------------------------
리터럴 (literal)
리터럴이란 "문자그대로" 라는 뜻이다.
In computer science, a literal is a notation for representing a fixed value in source code.
컴퓨터 사이언스에서, 리터럴은 "원시코드에 있는 어떠한 고정된 값"을 나타내기 위해 사용되는 용어이다.
원시 프로그램에서 어떠한 숫자 또는 기호로서 다른 데이터를 가리키는 역할을 하지 않고 그 자신이 바로 데이터로서 사용되는 것을 이른다.
예를들면, 어셈블러에서 LDA 100 이라고 하면, A 레지스터에 100번지에 있는 내용을 LOAD 하라는 것이지만,
LDA #100 이라고 하면, A 레지스터에 100 이라는 값을 넣으라는 것이 된다.
LDA 100 에서 LDA 는 load 라는 기능을 의미하고, 100은 100 이라는 숫자 자신이 아닌 번지수로 사용이 된 반면,
LDA #100 에서 #은 그 뒤에 있는 것을 리터럴로 취급하라는 표시 인데, 즉, 뒤의 100 이라고 하는 것은 그냥 100 그 자체일 뿐이다.
----------------------------------------------------------------------------------------------------
상수(constants)
고정된 값을 나타내는 또다른 개념중에 상수(constant)가 있는데, 리터럴은 상수하고는 조금 다른 개념이다.
상수는 수학으로 부터 비롯된 개념으로, 값이 변하지 않는 양을 말한다. 이것은 매우 포괄적인 개념이다.
아무튼 수학의 개념을 물려받아, 컴퓨터사이언스에서도 상수라는 개념을 쓰는데, 이것은 실제로는 값이 변하지 않는 변수이다.
그렇다고 하더라도, 컴퓨터 사이언스의 상수는 수학의 상수와 본질적으로 다르지 않은데, 수학에서, 변환에 대한 약간의 지식만 있으면 간단하게 이해할 수 있다.
가령, 다항 함수공간을 예로 들면, 각 함수에서 0차 항을 포함한 계수들은 값이 고정된 상수이지만, 그러한 함수들을 모아놓은 함수공간에서는, 계수들(0차항포함)이 각종 변환에서 오히려 변수역할을 한다는 것을 알수 있다. 일종의 듀얼리티 같은건데, 아무튼 하려는 짓이 무엇이냐에 따라 상수들도 변할 수 있다.
좀더 느낌이 오게 구체적으로 설명하자면... 이차함수 y = ax^2 + bx + c 에서 x 는 독립변수, y는 종속변수 이고, a,b,c 는 값이 고정된 상수들 이지만, 이차함수를 좨다 모아놓은 집합에서 임의의 원소 하나를 고르는 것은 (a,b,c) -> f 인 매핑이다. 즉, a,b,c 가 세개의 독립변수가 된다.
즉, 크게볼때 상수와 변수는 우리의 관심대상이 그것을 고정시켰느냐 아니냐의 차이일 뿐이다.
---------------------------------------------------------------------------------------------------
리터럴과 상수의 구분
이제 위와 같은 개념으로 부터 상수와 리터럴을 구별을 해보자.
CONST x := "abc"
CONST y := 10
위와 같이 x 에 문자열 abc 를 값이 변하지 않도록 고정시켜 배정했다고 치자.
(이렇게 고정되게 선언하는 구문은 프로그래밍 언어마다 차이가 있고, 우리는 특정 프로그래밍 언어에 대한 이야기를 하는 것이 아님에 유의한다.)
아무튼, 여기서 abc 라고 하는 것은 그냥 abc 자체를 나타내므로 리터럴이다.
반면, x 는 x 자체가 아니다. abc 라는 데이터를 가리키는 녀석이다. 즉, 리터럴이 아니다.
다시말해, x는 상수이고, abc는 리터럴이다. 특히 스트링 리터럴 이라고 한다.
y는 상수이고, 10은 리터럴이다. 특히, 숫자 리터럴 이라고 한다.
그런데, 리터럴들도 값이 변하지 않는다는 의미에서는 상수라고 할 수 있다.
실제로, 많은 고급언어에서 스트링 리터럴을 스트링 상수 라고 부른다.
즉, 리터럴이라는 개념은 상수라는 개념의 부분집합이다.
In contrast to literals, variables or constants are symbols that can take on one of a class of fixed values, the constant being constrained not to change.
Literals are often used to initialize variables.
위에서 보듯이, 리터럴은 변수를 초기화 하는데 자주 사용된다.
리터럴도 값이 변하지 않는다는 측면에서 상수이므로, 리터럴과 상수를 구분하는 다른 크라이테리어인 이름에 대해 생각해 보자.
리터럴은 상수와 마찬가지로 메모리 어딘가에 값이 변하지 않도록 저장이 되지만, 이름이 없다.
가령, 다음과 같이 두개의 문장이 있다고 하자.
1: CONST a : = 10
2: "abc"
해당 프로그래밍언어의 컴파일러 (혹은 인터프리터)는 a 라는 메모리 공간을 확보하고, 거기에 리터럴 10 을 집어넣는다. a 는 a 자체가 데이터가 아니라 다른 데이터, 즉, 10을 나타내는 이름이다.
두번째 문장의 경우, 문자열 abc 를 메모리 어딘가에 저장한다. 그러나 이것은 따로 이름이 없다. 그저 그 자체로 abc 일뿐이다. 굳이 말하자면, 그 자신이 이름이며 동시에 데이터이다. 물론 주소는 갖는다.
-----------------------------------------------------------------------------------------------
변수,상수,리터럴의 포함관계
변수는 변수명, 주소, 공간, 형식(읽기, 쓰기 등) 등의 요소를 갖는다.
상수는 변수에서 쓰기연산이 금지된 것이다.
리터럴은 쓰기연산이 금지되고, 변수명도 없는 것이다.
-----------------------------------------------------------------------------------------------
문자열상수의 평가값
컴파일러는 문자열 상수 (또는 리터럴) 를 보면, 메모리 어딘가에 해당 문자열을 위한 공간을 마련하여 저장한다. 이것은 리터럴이므로 별도의 이름을 갖지 않는다. 대신 어딘가에 저장되어있으므로, 주소는 갖는다.
문자열 상수의 평가값이 바로 문자열의 시작주소이다. 즉, 평가값은 const char* 형이고, 따라서, char* 형 변수에 배정할수 있다. pinrtf() 함수의 프로토타입에서 문자열 상수를 인자로 받을때, const char* 를 썼던것을 기억하자.
예.
#include<stdio.h>
int main(void)
{
char *p;
p = "Hello!\n"; // 메모리 어딘가에 문자열을 저장하고, 그 시작주소를 p가 포인팅하도록 한다.
printf(p); // p 가 포인팅 하는 곳에서 시작하여 NULL문자를 만날때까지 문자를 인쇄한다.
return 0;
}
문자열은 문자들의 배열이므로 위에서 char* 형으로 선언한것은 그냥 char형 배열로 선언해도 된다.
char str[] = "abc" ; 이것은 배열의 초기화 char str[] = { 'a' , 'b' , 'c' , '\n' }; 와 동일하다.
널스트링 (null string)
NULL 스트링은 아무것도 없는 스트링으로, 결과적으로 스트링의 끝을 알리는 NULL 문자만을 가지고 있다.
"" 은 널스트링이고, " " 은 공백을 가지고 있는 스트링으로 둘은 다르다.
예제. 널스트링의 출력
printf("You've got %d point%s.\n",pt,((pt==1)?"":"s"));
위 문장은, 점수가 1점이 아니면, 복수형인 points 를 쓴다. 반면, 1점이면, s대신 널스트링이 출력되어 point와 마침표사이에 공백없이 인쇄된다.