1차원 배열은 질리게 사용해봤다.
2차원 배열은 사용할 때 가끔 헷갈리는 점이 있어 정리해보려 한다.
아주 쉽게 요약하자면 아파트와 같다고 생각하면 쉽다.
1차원 배열은 예를 들어 쭉 뻗은 기차라고 생각하고, 2차원 배열은 아파트라고 외우자.
이런 배열을 선언하게 된다면 위 그림과 같은 이런 구조를 가진 배열이 생길 것이다. (이렇게 선언한다면 그림에서 값으로 적은 것은 0으로 다 초기화된다.)
int arr[5][5];
우리가 일반적으로 생각하는 가로-세로 순서가 아닌 세로-가로 순서로 진행된다.
arr[세로][가로]라고 머리에 박아두자 그냥
이런 식으로 선언하면 제일 보기 편하다.
1. int arr[2][3] = {
{1, 1, 1,},
{2, 2, 2}
};
2. int arr[2][3] = { 1, 1, 1, 2, 2, 2};
이와 같은 선언도 물론 가능하다.
3. int arr[4] = { 1, 2, 3, 4 };
기존의 우리가 사용하던 방식.
4. int arr[] = {1, 2, 3, 4,};
일차원 배열을 생성할 시 이렇게 배열을 선언하는 것도 가능하다.
컴파일러가 알아서 사이즈를 넣어준다. 개인적으로 이게 더 편한 거 같다.
5. int arr[];
이렇게는 선언이 불가능하다. 컴파일러가 배열의 사이즈를 가늠할 수 없기 때문이다.
6. int arr[][2] = { {1, 2} , {3, 4} , {5, 6}, {7} };
놀랍게도 이 배열은 컴파일된다.
이유는 처음 선언시 arr[][2]라고 두 번째 괄호에 2라고 입력했기에 원소가 2인 1차원 배열이 생기기 때문이다. 따라서 배열의 마지막 원소는 0이다.
// arr[3][0] == 7
// arr[3][1] == 0
7. int arr[2][0] = { {1,1,1}, {2,2,2,} };
이 선언은 또 다르게 컴파일링 되지 않는다.
c의 경우에는 맨 앞의 크기를 제외한 나머지 크기를 정확히 지정해줘야 한다는 룰이 있다.
따라서 6번 예제는 성공했지만, 7번의 경우에는 실패이다.
#include <stdio.h>
int main(){
int score[3][2];
int i,j;
int length = 3;
for(int i = 0; i < 3; i++){
for(int j = 0; j < 2; j++){
if(j == 0){
printf("%d번째 학생의 국어 성적을 입력하세요. \n", i+1);
scanf("%d", &score[i][j]);
}else if(j == 1){
printf("%d번째 학생의 수학 성적을 입력하세요. \n", i+1);
scanf("%d", &score[i][j]);
}
}
}
for(int i = 0; i < 2; i++){
printf("%d번째 학생의 국어 성적은: %d 입니다. 수학 성적은: %d 입니다. \n", i + 1, score[i][0] , score[i][1]);
}
return 0;
}
위의 예제를 하던 중 두 번째 for에서 scanf를 입력하고 난 후, 프로그램이 종료됐다.
생각해보니 scanf("%d", &score[i][j]);가 아닌 scanf("%d", score[i][j]);를 입력했다.
그래서 왜 주소를 의미하는 &. 즉 ampersand를 입력하지 않으면 scanf함수가 실행되지 않는지에 대해서 의문이 들었고, 구글링 해보았다.
- &(ampersand)는 변수의 주소를 의미한다.
- scanf()의 실행원리는 아래와 같다.
1. 값을 입력받음
2. 그 값을 레지스터에 저장. (레지스터는 일종의 임시 공간이다)
3. 해당 변수의 주소로 가서 그 조소가 가리키는 메모리에 현재 레지스터에 저장된 값으로 바꾼다.
4. 레지스터에 존재하던 값을 삭제한다.
int a;
char b[20];
문자열의 경우는 &를 입력하지 않아도 된다. 문자열 자체가 주소기 때문이다.
scanf("%d" , &a);
scanf("%s" , b);