문서의 임의 삭제는 제재 대상으로, 문서를 삭제하려면 삭제 토론을 진행해야 합니다. 문서 보기문서 삭제토론 배열 (문단 편집) === [[C언어|C]] === C에서도 기본적인 자료형으로 제공되며, 배열은 말 그대로 고정된 크기의 연속된 메모리이다. 실제 데이터가 위치하고 있는 가장 처음 메모리 주소를 갖고 있으며 배열 변수명 자체를 포인터로서 활용할 수 있다. 배열은 연속적인 위치를 보장하므로 (포인터 값 + 데이터형의 크기)의 형태로 다음 요소에 접근할 수 있다. [* 각 원소 사이에 빈공간(padding)이 들어가지 않는다는 얘기다. [[구조체]] 같은 경우는 정렬 제한을 맞추기 위해 맴버 변수 사이 혹은 그 끝에 빈공간이 들어갈 수 있다.] {{{int staticArray[10]; int* dynamicArray = (int*)malloc(sizeof(int)*10); }}} 위의 staticArray와 dynamicArray는 모두 staticArray{{{[3]}}}, dynamicArray{{{[3]}}}과 같은 형태로 접근할 수 있다. 정적으로 할당하면 무조건 컴파일 시간에 크기를 결정해야 하며 실행중에 크기를 변경할 수 없다. 동적으로 할당하게 되면 실행 시간에 크기를 결정할 수 있으며 재할당도 가능하나 프로그램 종료전에 반환 해주어야 한다. OS에 따라 적절하게 처리해 주기도 하지만 보통은 문제를 야기할 수 있다. C에서 주의할 것은, 배열의 크기는 유한하고 접근할 수 있는 범위도 처음 선언했던 크기만큼으로 제한되어 있지만, 실제로 배열 원소에 접근할 때에는 이게 맞는 범위에 접근하는지 전혀 체크하지 않는다. 때문에 잘못 짜면 컴파일할 때는 조용히 있다가 실행할 때 세그멘테이션 오류(Segmentation fault)가 발생하거나, 더 운이 안 좋은 경우에는 오류도 안 내면서 조용히 다른 범위의 메모리를 건드려 찾기 어려운 버그를 일으킨다. 사실 C에서 배열은 굉장히 애매한 지위를 차지하고 있는데, C에서 배열(배열 이름을 포함해서, 배열 타입을 결과값을 갖는 모든 수식)은 딱 세 가지 경우[* {{{sizeof}}} 연산자를 쓸 때, {{{&}}} 연산자를 쓸 때, 문자 배열을 문자열 상수로 초기화할 때.]를 제외하면 그냥 배열 첫 원소의 주소로 변환된다. 그래서 사실 C에서 배열에 대고 한다고 생각하는 연산들은 사실 '''그냥 포인터에 대고 하는 거랑 다를 게 없다.''' 심지어 n번째 원소에 접근하는 것도 배열 시작주소에서 n만큼 떨어진 메모리의 값을 구하는 것과 정확히 똑같다. 즉 {{{a[i] == *(a + i)}}}다.[* 농담하는 게 아니다. 실제로 {{{int a[3] = {2, 4, 8}; printf("%d", 1[a]);}}} 같은 코드가 멀쩡히 동작한다. [[http://www.cinsk.org/cfaqs/html/node8.html#6.11|#참고]] --그렇다고 실제로 프로그래밍할 때 저런 코드 쓰진 말고--] 그리고, 다른 게 하나 더 있는데, 배열 이름은 상수처럼 취급되어서 대입이 안 된다.[* 위에서 말한 규칙 때문이다. 대입 연산자 = 의 좌변에 배열 이름을 적으면 배열 첫 원소의 주소로 변환되며, 따라서 l-value가 아니게 된다. 배열을 매개변수로 가지는 구조체조차도 대입 연산이 되는데, 배열은 안 된다.][* 그래서 배열 이름을 '''포인터 상수'''라고도 한다.] 어떻게 보면 실행중에 포인터로 가리킨 배열의 길이를 알아내거나 배열 범위 검사를 안 하는 게 이런 이유 때문인데, 사실 C에는 배열 '자료구조'가 있는 게 아니라 '''그냥 연속된 메모리 공간을 직접 다루게 해 주는 것뿐'''이므로 길이를 알래야 알 수가 없는 거다. --그리고 여기서 우리는 [[C언어|C]]가 우리가 생각하는 것보다 훨씬 저수준 언어였다는 것을 알 수가 있다.-- 다차원 배열의 경우에는 얘기가 좀 더 복잡해지는데, 다차원 배열도 '''배열의 전체 영역이 전부 일렬로 메모리에 배치된다.''' 그래서 {{{int a[5][5];}}} 같은 배열이 있으면 {{{&a[0]}}}의 타입은 {{{int **}}}이 아니라 {{{int (*)[5]}}}이다. 그래서 일반 포인터는 일차원 배열처럼 쓸 수 있는데, 다차원 포인터는 다차원 배열처럼 쓸 수가 없다. 다차원 배열을 함수 인자로 넘길 때 {{{void f(int a[][5])}}}처럼 맨 앞 첨자만 {{{[]}}}로 쓰는 데에는 이런 이유가 있다.[* 사실 C언어에서는 함수 인자에 배열을 사용할 수 없다. 함수 인자에서 배열 타입으로 선언된 매개변수는 포인터 타입으로 자동 변환되어 처리된다. n차원 배열의 경우에는 (n-1)차원 배열에 대한 포인터로 변환된다.] 이게 문제를 엄청나게 복잡하게 만들기 때문에 사람에 따라서는 아예 다차원 배열을 '''전혀''' 쓰지 않고 전부 다차원 포인터에 동적할당시켜서 쓰는 경우도 있다. 그럼에도 중간에 다차원 배열을 인자로 받는 함수가 하나라도 있으면 골치썩는다. 차라리 일차원 배열을 강제 형변환해서 넘기는 게 더 쉽다.(...) 자세한 이야기는 다음 문서를 참조하자. [[http://www.cinsk.org/cfaqs/html/node8.html|C Programming FAQs - 6. Arrays and Pointers]][* 한글이 올바로 출력되지 않는다면 인코딩을 UTF-8로 고쳐보자]저장 버튼을 클릭하면 당신이 기여한 내용을 CC-BY-NC-SA 2.0 KR으로 배포하고,기여한 문서에 대한 하이퍼링크나 URL을 이용하여 저작자 표시를 하는 것으로 충분하다는 데 동의하는 것입니다.이 동의는 철회할 수 없습니다.캡챠저장미리보기