inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

(2026 최신!) 일주일만에 합격하는 정보처리기사 실기

다차원 배열과 문자열 배열

다차원 배열 포인터 질문있습니다

해결된 질문

33

전다영

작성한 질문수 1

0

  1. 20:28에서

const char *arr[2][2]={{Hello", "World"}, {"app", "dev"}};


이때 선언된 *arr포인터는 주소를 먹는 애로 알고 있는데, 그럼 우항의 {{Hello", "World"}, {"app", "dev"}} 이부분이 주소를 나타낸다는 뜻일까요? 추측하건대 배열이 변수 그자체로 주소를 나타내는것처럼 그것과 동일한 의미로 받아들이면 될까요?


제가 어거지로 이해해본것을 말하자면 ‘{{Hello", "World"}, {"app", "dev"}};’이 배열은 어딘가 이미선언된 k[2][2] 배열이고 k라고 우항에 쓴것과 마찬가지다..로 이해하면 되는걸까요..? ㅠ계속 이해가 안되면 그냥 문자열 배열이 들어오면 c언어의 한계때문에 선언할때 포인터를 사용한다. 이정도로만 암기하고 넘어가도 되나 싶네요


  1. 결국 선언된건 arr 이라는 배열인가요 arr이라는 포인터인가요?만약에 포인터라면 printf 할 때 arr앞에 별을 써야 해당 값이 나오는 거 아닌가요?

python java c 정보처리기사 정보처리산업기사

답변 3

0

주말코딩

안녕하세요. 답변 전에 C언어의 원칙 두 가지를 먼저 말씀드리겠습니다.

강의에서 다룬 내용이지만 헷갈리기 쉬운 부분이라 다시 정리합니다.


첫째, C언어에는 문자열 자료형이 따로 없습니다. char를 메모리에 연달아 놓고 끝에 \0을 붙인 것을 문자열로 취급합니다. 그래서 %s는 값을 받지 않고 문자열이 시작되는 메모리 주소를 받습니다. 그 주소부터 한 글자씩 출력하다가 \0을 만나면 멈춥니다. 이 부분을 많이들 착각합니다.


둘째, 배열 이름은 식에서 쓰이면 배열 첫 번째 원소의 주소로 바뀝니다. C언어 스펙이 그렇게 정해져 있습니다. (sizeof나 & 연산자와 함께 쓸 때만 예외입니다.)

이 두 가지를 바탕으로 질문을 풀어보겠습니다.


1번 질문

중괄호 전체가 주소를 뜻하지는 않습니다. 중괄호는 배열의 각 칸에 넣을 초기값 목록입니다. 다른 배열 이름(k)을 쓴 것과도 다릅니다. C에서는 배열을 다른 배열 이름으로 초기화할 수 없습니다.

주소에 해당하는 것은 중괄호 안의 각 문자열 리터럴입니다. "Hello"라고 쓰면 컴파일러가 메모리 어딘가에 H e l l o \0을 저장합니다.

이것도 일종의 char 배열이므로, 두 번째 원칙에 따라 식에서는 첫 글자 H의 주소로 바뀝니다. 결과적으로 4개의 주소가 4칸에 하나씩 들어갑니다.

arr[0][0] = "Hello"의 시작 주소
arr[0][1] = "World"의 시작 주소
arr[1][0] = "app"의 시작 주소
arr[1][1] = "dev"의 시작 주소

그러니 "C의 한계라서 포인터를 쓴다"고 외우실 필요는 없습니다.

"문자열 리터럴은 첫 글자의 주소다"만 기억하시면 됩니다.

포인터 대신 char arr[2][2][6]처럼 글자를 직접 복사해 담는 방식도 가능하고, 이 코드는 둘 중 포인터 방식을 고른 것입니다.


2번 질문

선언된 것은 배열입니다. 정확한 타입은 "const char* 4개를 담는 2x2 배열"입니다.

선언은 이름에서부터 읽으면 됩니다.

const char *arr[2][2]
arr        → arr은
[2][2]     → 2x2 배열이고
*          → 각 칸은 포인터이며
const char → 그 포인터는 const char를 가리킨다

참고로 const char (*arr)[2]처럼 괄호로 묶어야 arr 자체가 포인터가 됩니다.

printf에서 별을 붙이지 않는 이유는 첫 번째 원칙과 같습니다.

%s는 주소를 받는 형식이고, arr[0][0]에 이미 주소가 들어 있습니다.

printf("%s\n", arr[0][0]);    // Hello (주소를 넘김)
printf("%c\n", *arr[0][0]);   // H     (주소를 따라가 글자 하나를 꺼냄)
printf("%c\n", arr[0][0][1]); // e

별을 붙이면 문자열 전체가 아니라 첫 글자 하나(char)가 나오므로 %c로 출력해야 합니다.

0

전다영

답변 내용중

‘개념적으로는 다음과 비슷하게 이해할 수 있습니다. arr[0][0] = "Hello"; // "Hello"의 시작 주소’

이부분에서, 결국 이런식으로 코드를 작성하면 우항은 "Hello"라는 값 자체가 아니라 "Hello"의 시작 주소를 나타낸다는 말이죠? 이게 사실이라면 정말 근본적으로 잘못 이해하고 있었네요..ㅠㅠ

0

인프런 AI 인턴

안녕하세요, 인프런 AI 인턴입니다. 전다영님.

질문하신 선언은 다음과 같은 의미입니다.

const char *arr[2][2] = {
    {"Hello", "World"},
    {"app", "dev"}
};

arr은 문자열을 가리키는 포인터 4개를 담은 2×2 배열입니다.

arr[0][0] → "Hello"
arr[0][1] → "World"
arr[1][0] → "app"
arr[1][1] → "dev"

여기서 우항의 초기화 목록 전체가 이미 선언된 k[2][2] 배열의 주소를 의미하는 것은 아닙니다. {{...}, {...}}는 배열을 초기화하기 위한 초기값 목록입니다.

각 문자열 리터럴은 메모리에 저장되고, 문자열 리터럴을 사용할 때 해당 문자열의 시작 주소를 가리키는 포인터 형태로 변환되어 배열에 저장됩니다.

예를 들어 다음과 같은 관계입니다.

const char *arr[2][2] = {
    {"Hello", "World"},
    {"app", "dev"}
};

개념적으로는 다음과 비슷하게 이해할 수 있습니다.

arr[0][0] = "Hello";  // "Hello"의 시작 주소
arr[0][1] = "World";  // "World"의 시작 주소
arr[1][0] = "app";    // "app"의 시작 주소
arr[1][1] = "dev";    // "dev"의 시작 주소

다만 arr[0][0]이 문자열 전체를 직접 저장하는 것이 아니라, 문자열의 첫 번째 문자를 가리키는 주소를 저장한다는 점이 중요합니다.

printf("%s\n", arr[0][0]);       // Hello
printf("%c\n", arr[0][0][0]);    // H
printf("%s\n", arr[0][0] + 1);   // ello

또한 *arr에서 *는 arr 자체가 단순한 포인터 변수라는 뜻이 아닙니다. 선언에서는 배열 첨자 []의 우선순위가 *보다 높기 때문에 다음과 같이 해석됩니다.

const char *arr[2][2];

즉,

arr은 2×2 배열이고,
각 요소가 const char를 가리키는 포인터이다.

반면 아래 선언은 의미가 다릅니다.

const char **arr[2][2];  // const char*를 가리키는 포인터의 2×2 배열

질문하신 코드에서는 *arr이 하나의 포인터 변수를 선언하는 것이 아니라, arr[2][2]의 각 요소가 포인터라는 의미입니다.

문자열을 포인터 배열이 아닌 실제 문자 배열에 저장하는 방법도 있습니다.

char arr[2][2][6] = {
    {"Hello", "World"},
    {"app", "dev"}
};

이 경우에는 각 문자열을 저장할 실제 공간이 배열 안에 만들어집니다. "Hello"와 "World"는 널 문자 '\0'까지 포함해야 하므로 최소 6칸이 필요합니다. 포인터 배열은 문자열마다 길이가 달라도 사용할 수 있고, 문자 배열은 각 문자열에 확보할 최대 크기를 미리 정해야 한다는 차이가 있습니다.

관련 내용을 다룬 기존 답변을 함께 참고해 보세요.

  • 문자열 배열
    const char *arr[2][2]에서 각 배열 요소가 문자열의 시작 주소를 저장하는 방식과 char arr[2][2]와의 차이를 설명합니다.

  • 다차원 배열 입력 구문
    정수 배열과 문자열 포인터 배열에서 *가 붙는 이유를 설명합니다.

  • 이중배열 관련
    char *arr[2][2]와 문자 배열의 차이, 문자열의 널 문자에 대해 설명합니다.

문자열이 들어오면 무조건 포인터를 사용해야 하는 것은 아니지만, C언어에서는 문자열 리터럴을 여러 개 저장할 때 const char * 포인터 배열을 자주 사용합니다. 우선은 “배열의 각 칸에 문자열 자체가 아니라 문자열의 시작 주소가 저장된다”라고 이해하시면 충분합니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

모의고사 1회 계산문제 2개 맞았는데

0

6

1

업캐스팅 문제 예시 4번 부모 호출

0

17

1

모의고사 자료 해설이 너무 불친절하네요.

0

41

2

부모의 생성자 출력 관련

0

17

2

이론파트 재탕문제

0

20

0

누락코드

0

21

1

이론 파트 재탕

0

36

1

모의고사 5회

0

32

1

12분 10초 func(values, 0, 1)을 넣을 때

0

38

1

모의고사 1회 4번 문제와 관련한 질문이 있습니다.

0

40

2

재탕문제

0

57

1

재탕문제

0

38

0

파이썬 추가 코드

0

52

1

배열 포인터 출력 표시

0

53

2

포인터 증감 또는 값 증감

0

53

2

배열 포인터 함수 관련

0

52

2

실기 이론 통합 요약본 버전

0

66

2

업캐스팅 3번 문제 예시

0

63

2

push pop 설명 되어있는 강의가 몇강인가요?

0

52

1

모의고사 파일오류

1

84

3

모의고사 다운

0

58

1

업캐스팅 원칙

0

70

2

6분46초

0

61

2

공략법

0

71

1