코딩공부

2차원 배열과 포인터에 대해 Araboza 본문

Language/C언어

2차원 배열과 포인터에 대해 Araboza

초보코더 2017. 9. 26. 14:32
반응형

자그마치 며칠만에 돌아왔는지도 기억이 안나는 티스토리다! 블로그 꾸준히 쓰시는분들 정말 R.E.S.P.E.C.T.... 짱이다... 오늘은 내가 이것~저것하다가 문제가 생겼던 부분에 대해 얘기해보겠다!

그거슨 바로 2차원배열과 함수에서 2차원배열을 인자로 받는 부분...

이게 이래~저래 바꿔보고 찾아보면서 해도 자꾸 경고가 뜨길래 ㅠㅠ... 이거 찾느라 시간을 꽤 많이 잡아먹었다. 정작 코드는 단순한데...


1. 2차원배열이란 무엇인가?

2차원 배열이란 무엇일까?! 너무 간단하다...

1차원배열은 다들 알다시피

int arr[5] = {1,2,3,4,5}; 이런게 1차원 배열이다! arr라는 배열은 5개의 공간을 가지고, 각각 공간의 이름은 arr[0],arr[1],arr[2],arr[3],arr[4]이다. 0부터 시작함에 유의하자.

또 arr는 arr[0]의 주소를 의미한다. 즉, arr = &arr[0]이다. 다들 알거라고 믿는다. 원래 배열의 이름은 배열의 첫 주소값이다...


그렇다면 2차원배열을 생각해보자! 1차원배열을 행만존재하는 행렬이였다고 생각하면 2차원배열은? 물론 행과 열을 가지는 행렬이다. 즉,

int arr[3][4] = {{1,2,3,4},{4,5,6,7},{1,2,3,4}}; 이런 것이다. 


그런데!!!!!!!!!! 여기서 문제가 생긴다. 이게 내가 잘못 알고있던 부분인데...

arr[3][4]는 12개의 공간을 가지는 1차원 배열이 아니다!! 라는 것이다.(중요하다)

arr라는 배열은 3개의 공간을 가지는 배열이다. 즉, arr[0], arr[1], arr[2]를 가지는 배열이라는 것이다.


그리고 그 각각의 a[0],a[1],a[2]의 안에는 int [4]짜리 배열들이 들어가 있는것이다!


여기서 의문이 생기겠지... 아니 그럼 결국 똑같은소리잖아ㅡㅡ 라는건데... 맞다 ㅎ 사실마즘... 실제로 arr[3][4]는 메모리상에서 연속되는 12개의 공간을 차지하고 있다. 근데 우리가 앞으로 해야할 내용에서 저게 정말 중요한 개념이다 단순히 2차원 배열 arr[3][4]를 12칸짜리 1차원배열로 보는것과 arr[0],arr[1],arr[2]를 가지고 그 안에 int [4]짜리 배열이 존재한다고 이해하는 것은 전혀 다른것이니까!


1차원 배열에서 하던 얘기를 해보자. 배열의 첫 주소값은 배열의 이름이라고 했지?!

그럼 arr = 뭘까? 아마 많은 사람들이 arr = &arr[0][0] 이라고 생각했을 것이다. 배열의 첫 주소값이니까. 사실...아니다. 아까 얘기햇듯이 arr는 3칸짜리 배열이다. 첫 값은 arr[0] 두번째는 arr[1] 세번째는 arr[2]를 가지는. 그러므로 arr = &arr[0]이 맞는 표현이다. 이쯤에서 아니 이게 무슨개소리야?! 라고 하면서 &arr[0][0]이랑 &arr[0]이랑 값 같은데요?! 하는 사람들이 있...으려나? 어쨌든 사실 맞다ㅠㅠ &arr[0][0]의 값과 &arr[0]의 값은 같다! 근데 왜 &arr[0]이 맞다고 하느냐?


이제부터 나올 내용이 오늘 글의 메인내용이다.



2. 포인터와 2차원 배열

우리가 포인터와 배열을 배울때 둘을 혼용해서 쓰는 방식을 많이 사용해왔다. 

그 이유는? 물론 편리하니까. 함수의 parameter로 포인터를 설정하여 배열을 받는 작업도 많이 했을것이다. 나도 그랬다... 그런데 2차원 배열을 받아본 적 있는가? 1차원 배열과 같은 방식을 사용해서는 경고문구와 함께하는 내 코드의 모습을 봤을거다... 이것도 경험담이다......


그렇다면 어떻게 2차원배열은 포인터변수에서 어떻게 담아주는것이 옳을까?


1차원 배열에 대해 먼저 생각해보자. 다음 사진들을 보자.


아 정말 너무 간단하고 건전한 코드이다... arr라는 3칸짜리 배열을 만들고 p라는 포인터 변수를 만들어서 p라는 변수에 arr 즉, &arr[0]을 입력해준다. 그리고 나서 입력을 확인하기 위해 *p의 값, *(p+1)과 *(p+2)의 값을 각각 출력해 보았다. 물론


빌드오류같은건 없다! 하하하!


심지어 실행도 잘됌. 천줄 이천줄짜리 코드도 이렇게 잘됐으면 소원이없겠다... 흑흑..


일단 1차원 배열은 이런식으로 포인터를 이용해서 사용이 가능하다. 물론 같은 방식으로 함수의 인자로도 사용가능하다.

void check(int *p)

{

어떤함수

}


int main()

{

int arr[3] = {1,2,3};

check(arr);

}


해주면 아무 문제없이 실행 잘된다. 

참고로 printf를 printf("%d", p[0])으로, 또는 0부분을 1또는 2로 해줘도 실행 잘되고 경고도 안뜬다.

절대 캡쳐하기 귀찮아서 이렇게 쓴거 아니다. 해보라고 이런거다. ㅎㅎ...

2차원 배열에선 어떨까?! 꿈과 희망이 1도없는 2차원 배열을 사용한 코드이다 사진을보자.

1차원 배열과 동일하게 코드를 짜 보았다. 이때 arr는 무엇일까? 물론 &arr[0]이다.

빌드창에서 오류가뜬다 내용은 쉽게 얘기하면 서로 자료형이 다르다는 의미이다.

당연하지... *p는 단순히 하나의 수의 주소를 받는 포인터인데 arr 즉, &arr[0]에는 

int [4]가 들어가있으니까! 참조수준이 같을수가 없는 관계이다. 그런데

실행은된다 ㅎㅎ...왓더뻑...이 아니라 아까 얘기했다시피 arr는 연속적인 12개의 공간을 차지하고 있고 arr는 &arr[0]의 값을 갖는데 이 값은 또 &arr[0][0]과 같으므로 실행에는 문제가 없다! 그럼 문제는 뭘까?

이번 코드를 보자.

안된다!!! 갸아아아아악 

1차원때는 됐잖아ㅏㅏㅏ 갸ㅑㅑㅑㅑ아아아ㅏ악악 하지말고 알아보자. p는 arr의 주소값을 받기는 했지만 얘가 2차원 배열이라는 개념은 없다. 그냥 얘는 &arr[0]의 값을 받았을 뿐이다. 그런애한테 야 이거 2차원배열이니까 p[0][1]불러와! 하면 당연히 못하지... p입장에서는 아니 무슨 개소리야 이거 그냥 시작주소잖아 12개짜리 1차원배열 아니냐? ㅡㅡ 인것이다... 그럼 어떻게 해야할까? 인터넷에 찾아보니까 이렇게 배운사람들이 있다더라. 2차원 배열이니까 *두개 써주세요! 라고...

? ??? 무슨 소린진 잘 모르겠지만 우선 해보자.

이야!!! 문제가 사라졌어요!!! 빌드가 돼요 슨새임!!!

심지어 경고만 뜨고 오류만 뜨자나?! 완ㄴ전 이득인데?! 아까도 이랬는데 실행됐으니까 이번에도 될거야!!

해봐라. 암걸린다. 안된다. 자... 그럼 어떻게해야하나요ㅠㅠ...


정답을 알려주겠다!! 사실 정답은 아까부터 나오고 있었다... 오류목록에 내용이 보이는가? 간접참조수준이 뭐랑다르다고? int (*)[4]랑 다르단다. 그러면?

맞춰주면 되지!

아까부터 오류창에서 그렇게 '아니 이것좀 맞춰달라고 ㅠㅠ..'하던걸 맞춰 주었다. 맨 처음 했던 얘기 기억나는가? arr는 &arr[0]을 받고 arr[0]안에는 int [4]가 들어있다고. int [4]의 주소를 모두 받아줘야한다. 그럼 뭐가필요해? 당연히 4칸짜리 포인터 배열이지!!!

오류가 뜰리가없지

실행도 잘되지. 완전 펄펙.


한마디로... 2차원 배열을 포인터를 통해 사용해주려면 배열을 받을때 이 배열의 한 행에 몇개의 값이 들어있는지 알아두고 그 값을 int (*)[n]의 형태로 포인터에 저장해주면 된다! 1차원 배열때랑 똑같이 함수에서도 같은 방식으로 사용 가능하다. 이부분은 직접 해봐라!!! 해보고 안되면 물어보면 성심성의껏 알려드립니다...ㅎㅎ



자 오늘은 2차원배열과 2차원 배열을 포인터로 저장할때 저장법에 대해 알아보았습니다. 도움이 되었으면 좋겠습니다!! 혹시 본 내용이나 이전내용 아니면 블로그에 올라와 있지 않은 부분이라도 궁금한부분이 있으면 댓글로 달아주시면 열심히 공부해서 새로운 포스팅으로 올리거나 메일로 알려드리겠습니다! 구럼 20000...

반응형

'Language > C언어' 카테고리의 다른 글

문자열에 관한 고찰(1)  (0) 2017.10.08
Palindromic 수 찾기  (0) 2017.10.01
Scanf와 &  (2) 2017.09.07
Visual Studio의 scanf와 scanf_s  (0) 2017.09.05