Cプログラミング
 Computer >> コンピューター >  >> プログラミング >> Cプログラミング

C言語のポインタを使って2つの行列を乗算する方法をわかりやすく解説

ポインタ(pointer)とは、別の変数のメモリアドレスを格納するための変数です。C言語ではポインタを使うことでメモリを直接操作でき、効率的で高速なプログラムを作成できます。

ポインタの特徴

  • メモリ空間を節約できる。
  • メモリ上の位置へ直接アクセスするため、実行速度が速い。
  • メモリの動的な割り当てと解放が可能になり、メモリを効率的に利用できる。
  • リンクリストや木構造などのデータ構造と組み合わせて使用される。

ポインタの宣言・初期化・アクセス

まず、次のような通常の変数宣言を考えてみましょう。

int qty = 179;

この変数はメモリ上では、「qty」という名前、値「179」、そして固有のアドレスを持つ領域として表現されます。

宣言

ポインタの宣言は次のように行います。

int *p;

これは「p は別の整数型変数のアドレスを保持するポインタ変数である」という意味です。

初期化

ポインタ変数の初期化には、アドレス演算子(&)を使用します。

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

これにより、ポインタ p には変数 qty のアドレスが格納されます。

ポインタを通じた変数へのアクセス

ポインタが指し示す先の値にアクセスするには、間接演算子(*)を使用します。たとえば *p と書くと、p が指すアドレスに格納されている値(この場合は 175)を取得できます。

ポインタを使って2つの行列を乗算するCプログラム

以下は、ポインタ演算だけを使って2つの3×3行列の積を求めるCプログラムです。配列要素へのアクセスに通常の添字表記(mat[row][col])ではなく、*(*(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");
    }
}
/* 2つの行列を乗算する関数 */
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;
        }
    }
}

プログラムのポイント解説

行列の積では、結果の各要素は「第1行列の行成分」と「第2行列の列成分」の積の総和として計算されます。つまり、res[row][col] = Σ mat1[row][i] × mat2[i][col] という式になります。

このプログラムでは、その計算をすべてポインタ表記で実現しています。*(*(mat1 + row) + i) は「mat1 の先頭アドレスから row 行分進み、さらに i 列分進んだ位置の値」を意味し、mat1[row][i] と完全に同じ動作をします。同様に、入力時の *(mat + row) + col は要素のアドレスを表すため、scanf の引数としてそのまま渡せます。

実行結果

上記のプログラムをコンパイルして実行すると、次のような出力が得られます。

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

このように、添字演算子を使わずポインタ演算のみでも、行列の入力・表示・乗算を問題なく実装できることが確認できます。

  1. PythonとTensorFlowで2つの行列を乗算する方法を解説

    TensorFlowは、Googleが提供する機械学習フレームワークです。オープンソースとして公開されており、Pythonと組み合わせてアルゴリズムやディープラーニングアプリケーションなどを実装するために利用されています。研究用途から本番運用まで幅広く使われており、複雑な数学的演算を高速に処理できる最適化技術を備えているのが特長です。 その理由の一つは、NumPyと多次元配列を基盤としている点にあります。この多次元配列は「テンソル」と呼ばれます。TensorFlowは深層ニューラルネットワークの構築をサポートし、高いスケーラビリティを持ち、人気のデータセットが多数付属しています。また、GPUに

  2. PythonとTensorFlowを使って2つの行列を加算する方法

    TensorFlowは、Googleが提供する機械学習フレームワークです。オープンソースとして公開されており、Pythonと組み合わせてアルゴリズムやディープラーニングアプリケーションなどを実装するために広く利用されています。研究用途から本番環境まで幅広い場面で活用されており、複雑な数値計算を高速に実行するための最適化技術が多数搭載されています。この高い処理性能は、NumPyおよび多次元配列の仕組みによって支えられています。これらの多次元配列は「テンソル(tensor)」と呼ばれます。TensorFlowは深層ニューラルネットワークの構築を強力にサポートしており、高い拡張性を持つほか、代表的な