본문 바로가기
정글 2기/자료구조(C언어)

[C언어] 이중포인터를 이용하여 배열을 교환하는 방법

by Dean30 2021. 9. 14.
728x90

[C언어] 이중포인터를 이용하여 배열을 교환하는 방법

 

배열 A와 배열 B를 바꾸고 싶은 경우를 생각해보자. 배열을 일일히 바꿔주는 것은 너무나 번거로운 일이다. 쉽게 바꾸기 위해 포인터가 기리키는 값만 바꾸어 주면 되는데, 이 때 함수를 사용하고자 한다면 이중포인터를 사용해야 한다.

 

'함수에서 굳이 왜 이중포인터를 사용해야 될까?'를 고민한 끝에 얻은 결론은 dereference(역참조)를 해야 함수 밖 값의 변화를 줄 수 있기 떄문이다.

 

자 먼저 더 쉬운 예를 보자.

 

변수 값 서로 바꾸기

 

#include <stdio.h>

void swapNumber(int first, int second)    // 반환값 없음, int형 매개변수 두 개 지정
{
    int temp;    // 임시 보관 변수

    temp = first;
    first = second;
    second = temp;
}

int main()
{
    int num1 = 10;
    int num2 = 20;

    swapNumber(num1, num2);    // 변수 num1과 num2를 넣어줌

    printf("%d %d\n", num1, num2);    // 10 20: swapNumber 함수와는 상관없이 
                                      // 처음 저장한 10과 20이 출력됨

    return 0;
}

 

이 코드의 출력 값은 10 20 이다.

swapNumber 함수에서 분명 바꿔줬음에도 이런결과가 나온 것은 swapNumber 함수내에서 값을 바꿔줬지만, 이 변경은 함수 내에서만 유효하고 함수 밖으로 나올 땐 다시 원상복구 된다.

 

 

 

 

만약 함수를 통해 값을 변경하고자 한다면 변수들의 주소를 받아 포인터로 변경을 진행하면 된다.

 

#include <stdio.h>

void swapNumber(int *first, int *second)    // 반환값 없음, int 포인터 매개변수 두 개 지정
{
    int temp;    // 임시 보관 변수

    // 역참조로 값을 가져오고, 값을 저장함
    temp = *first;
    *first = *second;
    *second = temp;
}

int main()
{
    int num1 = 10;
    int num2 = 20;

    swapNumber(&num1, &num2);        // &를 사용하여 num1과 num2의 메모리 주소를 넣어줌

    printf("%d %d\n", num1, num2);   // 20 10: swapNumber에 의해서 num1과 num2의 값이 서로 바뀜

    return 0;
}

 

이 코드의 출력값은 20 10 이다. 이게 가능했던 이유는 함수내에서 dereference(역참조)를 통해 함수 밖에 있는 포인터가 가리키는 값 자체에 영향을 줬기 때문이다.

 

 

 

 

배열의 값 이중 포인터로 바꾸기

 

자 이제 워밍업이 끝났으니 같은 방식으로 배열을 바꾸기를 생각해보자.

 

#include <stdio.h>

void printArray(int* _array, int _len){
  for (int i =0; i < _len; i++)
    printf("%d ", _array[i]);
  printf("\n");
}

void swapArray2(int* _arrayA, int* _arrayB){
  int* temp = _arrayA;
  _arrayA = _arrayB;
  _arrayB = temp;
  printArray(_arrayA, 5);
  printArray(_arrayB, 5);
}


void main(void){
  int arrayA[5] = {11, 12, 13, 14, 15};
  int arrayB[5] = {21, 22, 23, 24, 25};

  int* pA = arrayA;
  int* pB = arrayB;

  swapArray2(pA, pB);

  printf("---------After swapArray()---------\n");

  printArray(pA, 5);
  printArray(pB, 5);
}

 

이렇게 바꾸면 함수내에서만 포인터(메모리 주소)가 바뀌고 함수 밖에선 arrayA와 arrayB의 값이 변하지 않는다.

 

그래서 함수 밖에서도 바꾸려면 포인터의 주소를 받아서 dereference를 통해 변경해야한다.

 

#include <stdio.h>

void printArray(int* _array, int _len){
  for (int i =0; i < _len; i++)
    printf("%d ", _array[i]);
  printf("\n");
}

void swapArray(int** _arrayA, int** _arrayB){
  int* temp = *_arrayA;
  *_arrayA = *_arrayB;
  *_arrayB = temp;
}

void main(void){
  int arrayA[5] = {11, 12, 13, 14, 15};
  int arrayB[5] = {21, 22, 23, 24, 25};

  int* pA = arrayA;
  int* pB = arrayB;

  swapArray(&pA, &pB);

  printf("---------After swapArray()---------\n");
  
  printArray(pA, 5);
  printArray(pB, 5);
}

짜잔 ! 이렇게 변경할 수 있다. 이게 제일 중요한 포인트이다.

 

 

 

물론 함수를 쓰지 않는다면 하기와 같이 일중포인터로 변경이 가능하다.

 

#include <stdio.h>

void printArray(int* _array, int _len){
  for (int i =0; i < _len; i++)
    printf("%d ", _array[i]);
  printf("\n");
}

void main(void){
  int arrayA[5] = {11, 12, 13, 14, 15};
  int arrayB[5] = {21, 22, 23, 24, 25};

  int* pA = arrayA;
  int* pB = arrayB;

  int* temp = pA;
  pA = pB;
  pB = temp;

  printf("---------After swapArray()---------\n");

  printArray(pA, 5);
  printArray(pB, 5);
}

 

 

 

 

여담이지만,

1차원 배열은 사실 1차원 포인터이고 2차원 배열은 2차원 포인터이다.

그래서 n차원 배열의 첫번째 값을 얻으려면 dereference를 n번 해줘야 한다.

 

 

 

참조) 코딩 도장, 유튜브 채널 HPC Lab. KOREATECH

 

 

 

 

 

728x90

댓글