본문 바로가기
컴퓨터 과학/데이터 구조

구조와 기능의 깊이 있는 이해: 포인터를 활용한 구조 전달

by 그마곤 2023. 11. 28.
반응형

구조와 기능 시리즈의 세 번째 부분에서는 구조 변수를 넘어 포인터를 사용한 구조 전달에 대해 다뤄보겠습니다. 이전 강의에서는 구조 변수를 함수 인수로 전달하는 방법을 살펴보았는데, 이번에는 구조의 크기가 클 때 효율적인 전달 방법을 배우게 됩니다.

구조와 기능의 깊이 있는 이해: 포인터를 활용한 구조 전달
구조와 기능의 깊이 있는 이해: 포인터를 활용한 구조 전달

구조 전달의 효율성: 복사 vs 포인터

프로그래밍에서 함수에 데이터를 전달하는 방식은 효율성에 큰 영향을 미칩니다. 특히, 구조체와 같이 큰 데이터를 다룰 때는 더욱 신중한 고려가 필요합니다.

복사본 전달의 문제점

구조체의 크기가 커질수록, 해당 구조체를 전체 복사하여 함수에 전달하는 것은 비효율적입니다. 메모리 공간과 시간 소모가 커지기 때문입니다.

포인터를 활용한 효율적인 전달

포인터를 이용하면 구조체의 주소만을 전달하므로 실제 데이터를 복사하지 않습니다. 이는 큰 구조체의 경우, 메모리 사용과 성능 면에서 탁월한 선택입니다.

실제 코드를 통한 비교

다음은 복사와 포인터를 사용한 두 가지 함수 호출의 비교입니다:

// 복사본 전달
void processByCopy(struct LargeStruct data) {
    // 함수 내에서 data를 복사하여 사용
    // ...
}

// 포인터를 통한 전달
void processByPointer(struct LargeStruct *dataPtr) {
    // 함수 내에서 주소를 통해 직접 접근
    // ...
}

실행 시간의 차이

구체적인 코드 실행 시간을 측정해 보면, 포인터를 이용한 전달이 메모리 및 실행 속도 측면에서 효율적인 것을 확인할 수 있습니다.

clock_t start, end;

start = clock();
processByCopy(data);  // 구조체 복사
end = clock();
printf("복사본 전달 소요 시간: %f 초\n", ((double)(end - start)) / CLOCKS_PER_SEC);

start = clock();
processByPointer(&data);  // 포인터 전달
end = clock();
printf("포인터 전달 소요 시간: %f 초\n", ((double)(end - start)) / CLOCKS_PER_SEC);

결론

따라서, 구조체의 크기가 크거나 데이터를 변경하지 않는 경우, 포인터를 사용한 전달이 메모리 및 실행 시간 면에서 효율적입니다. 프로그래머는 이러한 성능 차이를 고려하여 함수에 데이터를 전달하는 방식을 선택해야 합니다.

이처럼, 구조체 전달의 효율성은 프로그램의 성능 향상에 직결되므로, 실제 상황에서 어떤 방식을 사용할지 고려해 보는 것이 중요합니다.

 

포인터 활용 예시: C 언어에서의 구조체 다루기

이제 구조체와 포인터를 결합하여 데이터를 효율적으로 다루는 예시를 살펴보겠습니다. 아래 코드는 C 언어를 사용한 간단한 예시로, 포인터를 활용하여 구조체의 멤버에 접근하는 방법을 보여줍니다.

구조체 정의

#include <stdio.h>

// 좌표를 나타내는 구조체 정의
struct Point {
    int x;
    int y;
};

포인터를 사용한 함수 정의

// 구조체 포인터를 활용한 출력 함수
void printPoint(struct Point *ptr) {
    printf("X: %d, Y: %d\n", ptr->x, ptr->y);
}

메인 함수에서 활용

int main() {
    // 구조체 변수 초기화
    struct Point p1 = {10, 20};

    // 구조체 포인터를 통한 함수 호출
    printPoint(&p1);

    return 0;
}

설명 및 실행 결과

위 코드에서는 구조체 Point를 정의하고, 이를 가리키는 포인터를 활용하여 구조체의 멤버에 접근하는 함수를 정의했습니다. 메인 함수에서는 구조체 변수를 초기화하고, 해당 변수의 주소를 함수에 전달하여 출력합니다.

// 실행 결과
X: 10, Y: 20

코드 설명

  • struct Point 정의: 좌표를 나타내는 구조체 정의.
  • printPoint 함수: 구조체 포인터를 매개변수로 받아 해당 구조체의 멤버를 출력하는 함수.
  • 메인 함수: 구조체 변수를 초기화하고, 해당 변수의 주소를 printPoint 함수에 전달하여 출력.

포인터 활용의 이점

이 예시에서 포인터를 사용함으로써, 구조체의 복사를 피하면서도 함수에서 해당 구조체의 값을 활용할 수 있습니다. 특히, 구조체의 크기가 큰 경우, 이러한 방식은 효율성 면에서 상당한 이점을 제공합니다.

이처럼 포인터를 활용하면 구조체 데이터를 효율적으로 다룰 수 있으며, 프로그램의 성능을 향상시킬 수 있습니다.

실행 시간의 차이 비교

실행 시간을 측정하려면 코드에 시간을 측정하는 부분을 추가해야 합니다. C 언어에서는 clock 함수를 사용하여 간단한 실행 시간 측정이 가능합니다. 아래는 코드 수정과 실행 시간 비교를 위한 추가 내용입니다:

#include <stdio.h>
#include <time.h>

// ...

int main() {
    // 구조체 변수 초기화
    struct Point p1 = {10, 20};

    // 복사본 전달에 대한 시간 측정
    clock_t start_copy, end_copy;
    start_copy = clock();
    processByCopy(p1);  // 구조체 복사
    end_copy = clock();
    printf("복사본 전달 소요 시간: %f 초\n", ((double)(end_copy - start_copy)) / CLOCKS_PER_SEC);

    // 포인터 전달에 대한 시간 측정
    clock_t start_pointer, end_pointer;
    start_pointer = clock();
    processByPointer(&p1);  // 포인터 전달
    end_pointer = clock();
    printf("포인터 전달 소요 시간: %f 초\n", ((double)(end_pointer - start_pointer)) / CLOCKS_PER_SEC);

    return 0;
}

위 코드에서 processByCopy와 processByPointer는 각각 구조체를 복사하여 전달하는 함수와 포인터를 통해 전달하는 함수입니다. 이제 실행 결과에서 각각의 함수 호출에 걸리는 시간을 비교할 수 있습니다.

이 코드는 특정 환경에서 실행되므로 실행 환경에 따라 결과가 달라질 수 있습니다. 특히, 작은 프로그램에서는 실행 시간의 차이가 미미할 수 있습니다. 대규모 데이터나 복잡한 연산을 수행하는 경우에 실행 시간의 차이가 두드러지게 나타날 것입니다.

마무리

이를 통해 여러분은 구조체와 포인터를 조합하여 데이터를 효율적으로 다루는 방법을 학습하였습니다. 더 나아가, 프로그램의 성능 향상을 위해 포인터를 적절히 활용하는 습관을 기를 수 있습니다. 만약 추가적인 질문이나 궁금한 점이 있다면 언제든 댓글로 남겨주세요.

반응형