배열 char a 3 3 3 은 몇 개의

298p

Exercise

1. 배열이 10개의  원소를 가진다면 첫 번째 원소의 배열 번호는? 답 : 

① -1         ② 0          ③ 1          ④ 0 또는 1

2. 배열 char a[5][6]은 총 몇 개의 원소를 가지는가? 답 : ③

① 20          ② 24          ③ 30          ④ 42

3. 다음 중 잘못 선언된 배열을  모두  선택하여라. 답 : ②,③,④

① int a[2000+1];

② #define MAX 100

   #int a[MAX];

③ int v = 100;

   int a[v];

④ int a[100.25];

4. int a[100] = { 10 }; 으로 선언된 배열에서 a[99]의  초기 값은 무엇인가? 답 : ①

① 0

② 알 수 없다.

③ 전역 변수이면 0, 지역 변수이면 알 수 없다.

④ 99

5. int a[3][2] = { 1, 2, 3, 4, 5 }에서 a[1][2]의 초기 값은? 답 : ③

① 0         ② 4          ③ 5          ④ 알 수 없다.

6. 다음 중 잘못 초기화된 배열을 모두 선택하여라. 답 : ③

① int a[] = { 1, 2, 3, 4, 5 };

② int a[100] = { 1, 2, 3, 4, 5 };

③ int a[100] = { x, y, z };  //x, y, z는 변수

④ int a[100] = { 0, 0 };


우리는 여태 문자열을 저장하기 위해 string 자료형을 사용했다. 이 string 자료형은 C 에서 정확히 어떻게 정의되어 있을까? 문자열이 C에서 정의되는 방식과 메모리에 저장되는 방식을 알아보자.

● 문자열의 정의와 \0

int score 라는 변수의 값은 메모리 내에서 4 byte 를 차지한다고 공부했다. 그리고 int scores[3] 라는 배열은 3개의 값을 저장할 수 있었고 각 값은 int 이기 때문에 메모리 내에서 4 byte 를 차지한다. 이때 각 값에 대한 가상의 배열 이름이 붙여진다.(scores[0], scores[1], ... ) 컴퓨터는 각 값의 자료형에 따라 알아서 필요한 저장 공간을 계산하여 각 값들을 저장한다.

또한 char 는 각각 1 byte 씩 메모리 내에 저장되는 것을 알 수 있었다.

그렇다면 string 은 메모리내에서 어떻게 저장될까?

string은 char와 근본적인 관계가 있다. 만약 s 라고 하는 string이 있고 거기에 H I ! 를 저장한다고 하면 

s[0], s[1], s[2]로 문자열 내 각 문자를 가져올 수 있다.

즉, 문자열 변수의 이름이 s라면 배열을 다룰 때 처럼 각 문자에 접근할 수 있다는 것이다. 이는 매우 중요하다.

그렇다면 string 은 뭘까?

우리가 여태 사용했던 문자열 string 자료형의 데이터는 사실 문자(char) 자료형 데이터들의 배열이었다.

이제 우리는 string을 문자들의 배열로 정의한 것이다. 

그 이유는 여러 개의 문자들을 저장하는 것이 각 변수마다 하나의 문자를 저장한 것보다 유용하기 때문이다.

string s = "HI!" 가

char c1 = 'H'

char c2 = 'I'

char c3 = '!'  보다 유용하다는 이야기이다. 이는 배열을 정의할 때도 이해했던 개념이다.

즉 , string은 CS50 라이브러리 내의 자료형 중 하나로 일단 문자들의 배열이라고 생각하자. (물론 이 말도 엄밀하게는 잘못된 말이다.)

C 에서 string 을 선언할 때는 

string s = "HI!"; 라고 선언했다.

메모리 내에서는 s 라는 변수가 H I ! 를 가지게 된다.

그런데 string 은 조금 특이하게 다른 자료형들과는 다르게 정해진 크기를 가지지 않는다. 

그렇다면 변수가 s 혹은 name 등 과 같은 이름만 가지고 있다면 우리는 언제 string이 끝나는지를 어떻게 알 수 있을까?

우선 변수의 이름은 메모리 내에서 변수의 시작점에 대한 정보를 준다고 할 수 있다. 프로그램 내에서 s라는 변수를 만들면 컴퓨터는 해당 문자열의 첫 글자로 알아서 간다.

하지만, 문자열이 언제 끝나는지를 알려주는 정보도 필요하다.

이때 사용되는 것이 바로 널문자(널 종단 문자)이다. -> \0

※ \0 는 \n 과 마찬가지로 문자 2개 지만 1개 취급을 한다.

널 문자는 8개의 비트(1byte)가 모두 0을 나타내는 상태를 의미한다.

C에서 컴퓨터는 널 문자를 이용하여 문자열의 끝을 나타낸다. 즉 1 byte 를 모두 0으로 채워서 낭비하는 것이다.

이렇게 함으로써 메모리 상에서 다른 변수의 시작점을 이전 변수와 구분할 수 있게 된다.

즉, s 라는 문자열이 있으면 s[0]는 첫 글자이고 s[1]은 두번째 글자 s[2]는 세번째 글자이다.

그리고 \0 혹은 8비트의 0으로 표현되는 널 문자가 마지막 s[3]이 되는 것이다.

따라서 길이가 3 byte 인 문자열은 사실 4 byte를 차지하게 된다. 

이를 코드를 통해 직접 확인해보자.

배열 char a 3 3 3 은 몇 개의

names 라는 string 배열을 만들고 그 안에 4개의 string 들을 저장했다.

그리고 printf 를 통해서 names[0] 을 호출하여 출력해보니 EMMA 가 정확히 출력되는 것을 확인할 수 있다.

그렇다면 EMMA 라는 이름은 string 이고 string은 char들의 배열이라고 했으니 이 방법도 가능하다.

배열 char a 3 3 3 은 몇 개의

즉 형식지정자 %c 를 사용하고, 그에 맞는 각각의 string 의 char를 호출한 코드이다.

names[0][0] 은 E 를 의미하고, 

names[0][1] 은 M를 의미하고,

names[0][2] 은 M를 의미하고,

names[0][3] 은 A를 의미하는 것이다. 

이것이 바로 2차원 배열이다. [] 를 두 세트 사용한 것이다.

첫 번째 [] 는 이름들의 배열의 인덱스(어떤 배열의 특정 위치)를 나타낸다. 즉, names[0] 은 4개의 이름이 저장된 배열에서 EMMA의 이름으로 가라고 하는 의미이다.

그 뒤에 나오는 두 번째 []는 이름을 문자들의 배열로 보고 그 중에 0번째 문자. 위 코드에서는 첫 번째 글자인 E를 의미한다.

위 2차원 배열은 결국 문자열을 출력하는 것과 같다. C의 printf 함수와 같은 것이다. 사실 우리가 %s 에 변수명을 넣으면 printf가 하는 일은 이와 같이 일종의 루프를 만들고 첫 글자부터 반복해서 확인한다. ( '이 문자가 널 문자가 아니면 출력' 과 같은 방식)

그렇게 해서 E M M A 가 나오고 널문자를 확인하면 멈추게 된다. 즉, printf 함수가 EMMA 라는 string의 5번째 byte인 \0 혹은 8비트의 0이라는 것을 발견했다는 것이다.  

이것이 printf 함수의 작동방식이다.

그렇다면 이 널 문자도 확인할 수 있지 않을까??

배열 char a 3 3 3 은 몇 개의

names[0][4] 변수를 넣어주고 널 문자 확인을 위해 형식지정자를 %c 가 아닌 %i 를 통해서 출력한 결과

EMMA0 이 출력되는 것을 확인할 수 있다.

우리는 이렇게 컴퓨터 메모리를 원하는 대로 들여다 볼수 있게 된다. 단지 몇번째 위치인지만 지정해주면 알 수 있다.

이를 메모리의 관점에서 보면

각 1 byte 칸마다 E M M A \0 가 저장되고 R O D R I G O \0 이 저장되는 식이다. 

즉, names 라는 배열에 4개의 값이 있고 그 값들은 각각 1 byte 씩 메모리를 차지하고 또한 각각의 주소를 가지고 있는 것이다. E 는 names[0][0], M 은 names[0][1], M 는 names[0][2], A 는 names[0][3] 

첫 번째 [] 는 어떤 이름인지 찾고,

두 번째 [] 는 이름의 몇 번째 글자인지를 찾는 것이다.

또 다른 예시를 코드를 통해 봐보자.

배열 char a 3 3 3 은 몇 개의

string 은 char 들의 배열이기 때문에 

s 라는 string 변수도 배열이라고 할 수 있다.

따라서 

printf("%c\n", s[0]) 을 입력하면

string s 값의 첫 번째 글자인 s 가 출력됨을 확인할 수 있다.

자료출처 : 부스트코스 - https://www.boostcourse.org/cs112/lecture/119016?isDesc=false