Chapter.6 다차원 배열

  • 다차원 배열의 이해와 활용
    • 2차원, 3차원 배열은 존재, 4,5차원 배열은 X
      • ex) int arrOne[10];, int arrTwo[10][10];, int arrThree[10][10][10]; // 세로 가로 높이 순
    • 다차원 배열을 대표하는 2차원 배열의 선언
      • ex) int arr[3][4];
           
      • 즉 TYPE arr[세로길이][가로길이]; 이다
      • 이때 이 배열의 크기는 가로길이*세로길이*데이터크기 이다 // (앞의 배열은 48byte)
    • 2차원 배열요소의 접근
      • arr[N-1][M-1] = 20; // 세로 N열, 가로 M행 위치에 20 저장
    • 2차원 배열의 메모리상 할당의 형태
      • 메모리는 1차원이기 때문에 다음 행이 전 행의 마지막 열 뒤에 이어짐
      • ex) int 형 2차원 배열의 메모리 상태
               
    • 2차원 배열 선언과 동시에 초기화 하기
      • 중괄호 사이에 1행씩 중괄호로 선언하기

                     

      • 중괄호 안에 쉼표로 구분해서 선언하기
    •        
    • 배열의 크기를 알려주지 않고 초기화 하기
      • 가로 세로 길이 둘다 알려주지 않으면 절대 자동으로 길이를 설정할 수 없다
      • 따라서 2차원 배열을 설정할때는 가로길이는 꼭 넣어줘야 한다
      • ex) int arr1[ ][4] = {1, 2, 3, 4, 5, 6, 7, 8};
  • 3차원 배열
    • 3차원 배열의 논리적 구조
      • 정육면체 구조와 동일하다고 생각하면 된다
      • int arr[2][3][4]; // 높이2, 가로3, 세로4 인 int 형 3차원 배열
      • 물론 배열의 크기 또한 (높이 * 가로 * 세로 * 자료형 사이즈) 이다
    • 3차원 배열의 선언
      • 앞서 설명한 2차원 배열이 여러개 모여있는 형태이다

Chapter.7 포인터의 포인터

  • 포인터 변수를 가리키는 이중 포인터 변수(더블 포인터 변수)
    • 주소 값을 저장하는건 똑같은 포인터 변수를 가르키는 포인터 변수이다
    • ex) double num;, double* ptr = #, double** dptr = &ptr;
           
    • *dptr // ptr을 의미, **dptr, *(*dptr) // num 을 의미
  • 포인터 변수 대상의 Call-by-reference
    • 이전에 swap 함수 때와 같이 포인터 변수 대상으로 swap 함수를 선헌한다
      1. void SwapIntPtr(int *p1, int *p2) 일 때
        •  위처럼 ptr이 가리키는 주소는 변하지 않는다
      2. void SwapIntPtr(int **p1, int **p2) 일 때
        •  이처럼 ptr1의 주소를 불러오기 때문에 ptr의 값 자체를 변경시킬 수 있다
    • 포인터 배열과 포인터 배열의 포인터 형
      • Chapter.3 에서 설명한 포인터 배열에 대한 부가설명
      • int* arr1[20]; 선언시 포인터 배열의 이름인 arr1이 가리키고 있는 것은 배열 첫번째의 주소 즉 arr1은 이중포인터 이다
  • 다중 포인터 변수와 포인터의 필요성
    • 이중 포인터 뿐만 아니라 삼중, 사중으로 *연산자를 추가하여 다중 포인터를 생성할 수 있다
    • 포인터는 데이터의 효율적인 표현 및 저장방법을 위해 존재한다!

Chapter.8 다차원 배열과 포인터의 관계

  • 1차원 배열이름의 포인터 형과 2차원 배열이름의 포인터 형
    • 1차원 배열일 경우, int arr[10]; // arr 은 int형 포인터
    • 2차원 배열은 단순히 ~형 포인터로 선언할 수 없다
  • 2차원 배열 이름이 가리키는 것들?
    • 우선 int arr2d[3][3]; 인 배열을 선언했다면, arr2d가 가리키는 것은 인덱스 기준으로 [0][0]인 첫번째 요소 이다!
      • 그러나 arr2d와 마찬가지로 arr2d[0], arr2d[1] 또한 같은 의미를 가진다 // arr2d[0] 은 [0][0]을, arr2d[1]은 [1][0]
      • arr2d와 arr2d[0]는 가리키는 것은 같지만 의미하는 것은 다르다(sizeof또한 다르다)
        1. arr2d 는 첫번째 요소를 가리키되 배열 전체를 뜻하므로 sizeof(arr2d) 선언시 36byte가 반환된다
        2. arr2d[0]는 첫번째 요소를 가리키되 첫번째 행을 뜻하므로 sizeof(arr2d[0]) 선언시 12byte가 반환된다
    • 배열이름 기반의 포인터 연산: 배열이름에 +1
      • 1차원 배열의 경우 sizeof(TYPE)만큼 크기가 더해진다 즉 TYPE이 같다면 더해지는양은 동일!
      • 2차원 배열이 경우 sizeof(TPYE)*가로길이 만큼 크기가 더해진다 따라서 TYPE이 같아도 더해지는 양이 다르다
    • 최종결론! 2차원 배열이름의 포인터 형
      • 2차원 배열 이름의 포인터 형에 담겨야 하는 정보 두가지
        1. 가리키는 대상은 무엇인가?
        2. 배열이름(포인터)를 대상으로 증감연산시 실제 증가하는 양(byte)는 얼마인가
      • ex) int arr[3][4]인 경우
        • 가리키는 대상은 int형 변수이고, 포인터 연산시 sizeof(int)*4 크기단위로 증가, 감소 된다!
        • -> int (*ptr) [4]; // (가리키는 대상) (포인터) (가로길이)
        • 이러한 표현을 "배열 포인터 변수" 라 한다
      • 2차원 배열이름의 특성과 주의사항!
        • 주의! "배열 포인터"와 "포인터 배열"을 혼동하지 말자!
          • 배열 포인터는 배열을 가리키는 포인터의 선언! (int (*whoA) [4];)
          • 포인터 배열은 포인터로 이루어진 배열의 선언! (int *whoB [4];)
        • 2차원 배열을 함수의 인자로 전달하기
          • 선언법 ex) void Arr2(int (*arr)[4]) or void Arr2(int arr[ ][4]);
          • sizeof(arr)은 배열 전체 크기, sizeof(arr[0])은 배열의 가로크기, sizeof(arr)/sizeof(arr[0])은 세로크기 이다
        • 2차원 배열에서도 arr[i]와 *(arr+i)는 같다
          • int arr[3][2]; 선언시 3행 2열(마지막 요소)에 접근하는 법
          • cf) 2차원 배열에서의 덧셈
            • arr+i = arr[0][0] + i*Type*가로길이
            • arr[1] + i = arr[1][0] + i*Type 
              1. arr[2][1]
              2. (*(arr+2))[1] // arr+2경우 가로길이*2가 더해짐 //*(arr+2) 는 arr[2][0]
              3. *(arr[2]+1) // arr[2][0] + 1 
              4. *(*(arr+2)+1) // arr[2] = *(arr+2)

 

'IT공부 > 윤성우 열혈 C프로그래밍' 카테고리의 다른 글

C언어의 깊은 이해_1  (0) 2022.02.07
포인터와 배열의 시작_4  (0) 2022.02.07
포인터와 배열의 시작_2  (0) 2022.02.04
포인터와 배열의 시작_1  (0) 2022.02.02
C언어의 기본_4  (0) 2022.01.29

+ Recent posts