
포인터는 문자열 상수를 가리킬 수 있습니다. 여러 문자열을 처리할 때, 문자열을 가리키는 포인터들을 배열로 한꺼번에 저장하면 편리합니다.
#include <stdio.h>, int main(void), return 0; 등 구문은 특별히 필요하지 않은 경우 생략합니다.char *형 포인터printf("%s", "lgtwins");
// [출력] lgtwins

char형 배열 형태로 메모리에 별도로 보관함char형 배열의 첫 요소의 주소로 해석됨"lgtwins"를 char형 배열로 별도 저장"lgtwins"는 배열의 첫 요소인, 문자 l의 주소로 해석됨printf는 해당 주소부터 시작하는 문자열을 출력printf("첫 번째 문자: %c\n", *"lgtwins");
printf("두 번째 문자: %c\n", *("lgtwins" + 1));
// "lgtwins"[2]는 *("lgtwins" + 2)와 동일 연산
printf("세 번째 문자: %c\n", "lgtwins"[2]);
// [출력]
// 첫 번째 문자: l
// 두 번째 문자: g
// 세 번째 문자: t
* 연산자로 해당 주소의 문자에 접근하고*"lgtwins" = 'L' 처럼 문자열 상수의 값을 직접 수정할 순 없음🤔 한국어 문자열도 위 코드처럼 주소 단위로 접근할 수 있나요?
printf("첫 번째 문자: %c\n", *"엘지트윈스");
printf("두 번째 문자: %c\n", *("엘지트윈스" + 1));
printf("세 번째 문자: %c\n", "엘지트윈스"[2]);
printf("전체 문자열: %s\n", "엘지트윈스");
// [출력]
// 첫 번째 문자: �
// 두 번째 문자: �
// 세 번째 문자: �
// 전체 문자열: 엘지트윈스
char형 배열에 문자당 1바이트씩 저장됩니다."엘지트윈스"의 시작 주소를 char 단위로 해석하면,"엘" 의 3바이트 중 첫 1바이트만 읽게 됩니다.문자열의 시작 주소를 가리킵니다.%c로 출력하려고 하면 깨진 문자가 출력됩니다.char *형 포인터char *형 포인터에 대입할 수 있음char *pc = "LG Twins"; // pc는 문자열 배열의 시작 주소를 가리킴
printf("2025년 한국시리즈 우승팀은 %s입니다!\n", pc);
pc = "Austin Dean"; // pc는 변수, 새로 대입 가능
printf("MVP는 %s 선수입니다!\n", pc);
// [출력]
// 2025년 한국시리즈 우승팀은 LG Twins입니다!
// MVP는 Austin Dean 선수입니다!

printf는 pc가 가리키는 문자를 출력\0)를 만날 때까지 반복char형 배열은 선언할 때 크기를 명시해야 했지만 (char arr[20]), char *형 포인터는 크기 상관없이 문자열 상수만 대입하면 바로 사용 가능⚠️주의할 점
// 올바른 사용법
char arr[20];
scanf("%s", arr);
// 잘못된 사용법
char *pc;
scanf("%s", pc);
scanf("%s", pc)와 같이 직접 값을 입력할 수는 없습니다.pc가 유효한 메모리 공간을 가리키지 않아, 오류가 발생합니다. malloc을 사용해, pc가 가리킬 메모리 공간을 먼저 할당해야 합니다.char형 배열은 선언과 동시에 메모리 공간이 할당되므로, 에러가 발생하지 않습니다.⚠️주의할 점 2
// 올바른 사용법
char arr[20] = "hello";
scanf("%s", arr);
// 잘못된 사용법
char *pc = "hello";
scanf("%s", pc);
pc는 문자열 상수 "hello"를 가리킵니다.scanf로 해당 메모리의 내용을 덮어쓰려 하면 오류가 발생합니다.strcpy도 안 됩니다!!!char형 배열의 경우 문자열 상수를 복사한 뒤 수정 가능한 메모리 공간에 저장하므로, 이후에 내용을 덮어씌워도 문제가 없습니다.char *형 포인터 배열char *형 포인터의 배열은, 여러 개의 문자열을 처리할 때 사용 가능char *parr[4]; // 포인터 배열 선언
// 각 char*형 포인터에 문자열 대입
parr[0] = "hello"; // 별도로 저장된 배열의 첫 주소 대입
parr[1] = "mr.";
parr[2] = "my";
parr[3] = "yesterday";
for (int i = 0; i < 4; i++){
printf("%s ", parr[i]);
}
// [출력] hello mr my yesterday

*을 붙임char *형 포인터 4개를 갖는 행렬이므로, char *parr[4]로 선언char *형 포인터인 메모리 공간이 할당됨parr의 각 요소는, 개별 문자열의 시작 주소printf로 각 문자열 출력 가능char *parr[4] = {"hello", "mr.", "my", "yesterday"};
char arr[4][15] = {"hello", "mr.", "my", "yesterday"};
char*형 포인터 배열을 초기화할 수 있음char형 배열의 초기화와 유사하지만, 실제 저장 방식은 다름parr의 각 요소에는, 별도로 저장된 문자열의 시작 주소만 저장됨arr의 각 요소에는, 문자열 전체가 저장됨// 1차원 배열 선언
int arr1[4] = {15, 8, 35, 17};
int arr2[4] = {10, 47, 59, 4};
int arr3[4] = {5, 11, 13, 16};
// 포인터 배열에 각 배열의 시작 주소 저장
int *parr[3] = {arr1, arr2, arr3};
// 2차원 배열처럼 출력
for (int i = 0; i < 3; i++){
for (int j = 0; j < 4; j++){
printf("%5d", parr[i][j]);
}
printf("\n");
}
// [출력]
// 15 8 35 17
// 10 47 59 4
// 5 11 13 16

arr1, arr2, arr3은, 각 배열의 시작 주소int형을 가리키므로, int *형 포인터 배열인 parr에 저장할 수 있음parr[i][j]: 포인터 연산을 통해 값에 접근arr3이 300번지부터 할당됐을 때, parr[2][2] 출력하기parr[2]는 arr3의 시작 주소 300을 가리킴parr[2][2] -> *(parr[2] + 2)로 해석됨parr[2]는 4바이트 int형을 가리키므로, parr[2] + 2 -> 300 + 2 * 4 -> 308*(308)으로 arr3[2]인 13에 접근다음과 같은 코드가 있을 때, 보기 중 배열 요소의 사용이 잘못된 것을 고르세요.
char *pa = "apple"; // char *형 포인터
char ary[] = "banana"; // char형 배열
char *pary[4]; // char *형 포인터 배열
pary[1] = pa;pary[2] = ary;pary[3] = "mango";pary[4] = "orange";
pary는 char *형 포인터의 배열이므로, 배열의 원소는 char *형이여야 함.char 배열의 이름, char *형 포인터 변수가 들어갈 수 있음.pa는 char *형 포인터. -> 옳은 설명ary는 char형 배열명이며, 첫 번째 요소의 주소로 해석되므로 char *형. -> 옳은 설명"mango"는 문자열 상수로, 문자열은 char형 배열 형태로 별도로 저장됨. 이때 "mango"는 해당 배열의 첫 번째 요소의 주소로 해석되므로 char *형. -> 옳은 설명pary의 배열 요소는 4개이므로, 인덱스 0-3까지 사용할 수 있음. pary[4]는 할당된 범위를 벗어남. -> 틀린 설명