문자열은 배열입니다.
지금까지의 문자열을 이렇게 선언하였습니다.
char str1[] = "Hello"; //배열의 길이는 자동으로 계산
배열의 이름은 포인터상수입니다.
그렇다면 문자열을 포인터 변수에 저장할 수 있을까요?
다음과 같은 형태가 될 것입니다.
char * str2 = "Hello";
위의 두가지 상황에 대해 메모리의 할당 형태를 비교해보면 다음과 같습니다.
str1은 포인터상수이므로 다른문자열을 가리킬수 없습니다.
str2는 포인터변수이므로 다른 문자열을 가리킬수도 있습니다.
str1 = "World!"; // 이것은 에러입니다.
str2 = "World!";
배열로 할당받은 문자열의 일부 문자는 변경이 가능하지만,
포인터 변수가 가리키는 문자열의 일부 문자는 변경할 수 없습니다.
*(str1 + 3) = 'A'; // HelAo 로 변경 가능
*(str2 + 3) = 'A'; // 이것은 에러입니다.
str1처럼 배열로 할당받은 문자열을 변수 형태의 문자열 이라고 합니다. str2처럼 포인터변수에 정의된 문자열은 상수 형태의 문자열 이라고 합니다.
#include <stdio.h>
int main(void) {
char str1[] = "Hello"; // 변수 형태의 문자열
char *str2 = "Hello"; // 상수 형태의 문자열
printf("str1의 길이 : %d\n", sizeof(str1));
printf("str2의 길이 : %d\n", sizeof(str2));
// str1 = "World!"; //이것은 에러입니다.
str2 = "World!"; // 포인터 변수는 다른 문자열을 대상으로 변경 가능
*(str1 + 3) = 'A'; // 변수 형태의 문자열의 문자는 변경가능
// *(str2 + 3) = 'A'; //이것은 에러입니다.
printf("%s %s\n", str1, str2);
return 0;
}
상수형태의 문자열은 어디서든 선언할 수 있습니다.
char * str = "Hello";
이러한 코드가 있다면 "Hello"는 메모리 어딘가에 저장된 주소값이 될 것이고,
예를들어 그 주소가 0x123456번지에 저장이 되었다면 다음과 같은 형식이 될것입니다.
char * str = 0x123456";
포인터도 변수 임으로 포인터 변수로 이루어진 배열을 선언할 수 있습니다.
그래서 주소값이 저장가능한 배열을 가리켜 포인터배열 이라고 합니다.
#include <stdio.h>
int main(void) {
int a = 10, b = 20, c = 30;
int *ptrArr[] = { &a, &b, &c }; // int형 포인터 배열
printf("%d\n", *ptrArr[0]);
printf("%d\n", *ptrArr[1]);
printf("%d\n", *ptrArr[2]);
return 0;
}
문자열은 배열이기 때문에 포인터 배열의 형식으로 저장할 수 있습니다.
#include <stdio.h>
int main(void) {
char *strArr[] = { "One", "Two", "Three" }; // 문자열 배열
printf("%s\n", strArr[0]);
printf("%s\n", strArr[1]);
printf("%s\n", strArr[2]);
return 0;
}
위의 예제처럼 쌍따옴표로 표현되는 문자열은 메모리 공간에 저장된 후 그 주소값을 반환하게 됩니다.
strArr[0] 은 포인터 변수이고 "One" 이라는 문자열을 가리키고 있는 것입니다.