Computer >> 컴퓨터 >  >> 프로그래밍 >> C 프로그래밍

C 언어에서 포인터를 사용해 두 행렬을 곱하는 방법

포인터(Pointer)는 다른 변수의 메모리 주소를 저장하는 변수입니다. C 언어에서 포인터를 제대로 이해하면 배열, 문자열, 동적 메모리 관리 등을 훨씬 효율적으로 다룰 수 있습니다.

포인터의 주요 특징

  • 포인터를 사용하면 메모리 공간을 절약할 수 있습니다.
  • 메모리 위치에 직접 접근하기 때문에 실행 속도가 빠릅니다.
  • 포인터를 활용하면 메모리를 효율적으로 접근할 수 있으며, 메모리를 동적으로 할당하고 해제할 수 있습니다.
  • 연결 리스트, 트리 등 다양한 자료구조 구현에 필수적으로 사용됩니다.

포인터의 선언, 초기화 및 접근

다음 문장을 예로 들어 살펴보겠습니다.

int qty = 179;

이 변수는 메모리에서 아래 그림과 같이 표현됩니다.

C 언어에서 포인터를 사용해 두 행렬을 곱하는 방법

1. 포인터 선언

포인터는 다음과 같이 선언할 수 있습니다.

int *p;

이 선언문의 의미는 'p'가 다른 정수(int) 변수의 주소를 저장하는 포인터 변수라는 것입니다.

2. 포인터 초기화

포인터 변수를 초기화할 때는 주소 연산자(&)를 사용합니다.

예를 들면 다음과 같습니다.

int qty = 175;
int *p;
p = &qty;

위 코드에서 p에는 변수 qty의 메모리 주소가 저장됩니다.

3. 포인터를 통해 변수 값 접근하기

포인터가 가리키는 변수의 실제 값을 읽거나 수정하려면 간접 참조 연산자(*), 즉 역참조(dereference) 연산자를 사용합니다.

예제: 포인터로 두 행렬 곱하기

다음은 포인터를 사용하여 두 개의 3x3 행렬을 곱하는 완전한 C 프로그램입니다. 배열 요소에 접근할 때 인덱스 대신 *(*(mat + row) + col) 형태의 포인터 연산을 사용한 점에 주목하세요.

#include <stdio.h>
#define ROW 3
#define COL 3

/* 함수 선언 */
void matrixInput(int mat[][COL]);
void matrixPrint(int mat[][COL]);
void matrixMultiply(int mat1[][COL], int mat2[][COL], int res[][COL]);

int main() {
    int mat1[ROW][COL];
    int mat2[ROW][COL];
    int product[ROW][COL];

    printf("Enter elements in first matrix of size %dx%d\n", ROW, COL);
    matrixInput(mat1);

    printf("Enter elements in second matrix of size %dx%d\n", ROW, COL);
    matrixInput(mat2);

    matrixMultiply(mat1, mat2, product);

    printf("Product of both matrices is : \n");
    matrixPrint(product);

    return 0;
}

void matrixInput(int mat[][COL]) {
    int row, col;
    for (row = 0; row < ROW; row++) {
        for (col = 0; col < COL; col++) {
            scanf("%d", (*(mat + row) + col));
        }
    }
}

void matrixPrint(int mat[][COL]) {
    int row, col;
    for (row = 0; row < ROW; row++) {
        for (col = 0; col < COL; col++) {
            printf("%d ", *(*(mat + row) + col));
        }
        printf("\n");
    }
}

void matrixMultiply(int mat1[][COL], int mat2[][COL], int res[][COL]) {
    int row, col, i;
    int sum;
    for (row = 0; row < ROW; row++) {
        for (col = 0; col < COL; col++) {
            sum = 0;
            for (i = 0; i < COL; i++) {
                sum += (*(*(mat1 + row) + i)) * (*(*(mat2 + i) + col));
            }
            *(*(res + row) + col) = sum;
        }
    }
}

코드 핵심 설명

  • matrixInput(): *(*(mat + row) + col) 대신 (*(mat + row) + col)처럼 주소 자체를 전달하여 scanf로 값을 직접 입력받습니다.
  • matrixPrint(): 역참조 연산자를 이용해 각 행렬 요소를 화면에 출력합니다.
  • matrixMultiply(): 행렬 곱셈의 기본 원리인 "첫 번째 행렬의 행(row)과 두 번째 행렬의 열(column)의 내적"을 삼중 반복문으로 계산합니다.

실행 결과

위 프로그램을 컴파일 후 실행하면 다음과 같은 출력을 확인할 수 있습니다.

Enter elements in first matrix of size 3x3
2 3 1
2 5 6
2 6 8
Enter elements in second matrix of size 3x3
1 2 1
2 3 4
5 6 7
Product of both matrices is :
13 19 21
42 55 64
54 70 82

이처럼 포인터 연산만으로도 일반적인 배열 인덱스 방식(mat[row][col])과 동일하게 행렬 입출력과 곱셈을 처리할 수 있습니다. 포인터와 2차원 배열의 관계를 이해하는 데 매우 좋은 예제이니 직접 코드를 작성해 보며 익혀보시기 바랍니다.