【C++】関数へポインタを渡す方法|配列を渡すのと何が違う?

目次

はじめに

前回の記事では、void func(int arr[])という形で、関数に配列を渡す方法を学びました。その際、「配列を渡す際、実際には配列の先頭アドレスが渡される」と解説しました。

では、もっと直接的に、void func(int* p)のように「ポインタ」を引数として宣言した場合はどうなるのでしょうか? arr[]*p、この2つの書き方に違いはあるのでしょうか。今回は、この疑問を解き明かしながら、ポインタを引数として活用する方法を解説します。


結論:関数引数において int arr[]int* arr は同じ意味

いきなり結論からお伝えすると、関数の引数として書く場合、int arr[]int* arrは、コンパイラにとっては全く同じ意味として解釈されます。

どちらの書き方でも、関数は「int型を指すポインタ」を受け取る、という点では同じです。

  • int arr[]: 「配列が渡されることを期待している」という開発者の意図を伝えやすい、より可読性を意識した書き方。
  • int* p: 「ポインタ(アドレス)を受け取る」という、より仕組みに忠実な書き方。

どちらを使うかはコーディングスタイルによりますが、どちらも根本的にはポインタを扱っている、ということを理解するのが重要です。


ポインタ渡しでも「配列のサイズ」は失われる

int arr[]int* pが同じ意味ということは、残念ながら、前回の記事で解説した「配列のサイズ情報が失われる」という弱点も共通しています。

ポインタはあくまで「ある一点のアドレス」を指しているに過ぎず、その先にデータが何個続いているかまでは分かりません。そのため、ご提示のコードのように、関数内でループ回数を5のような固定値にしてしまうと、その関数は特定のサイズの配列でしか使えない、汎用性の低いものになってしまいます。


実践コード:ポインタ記法で平均値を求める

解決策は前回と全く同じです。「配列のサイズも、別の引数として一緒に渡す」。

ここでは、関数をdouble calculate_average(int* p_data, int size)とポインタ記法で宣言し、内部ではポインタ演算を使って平均値を計算する、より実践的なコードを見ていきましょう。

C++コード例

#include <iostream>
using namespace std;

// 関数のプロトタイプ宣言(引数をポインタ記法で記述)
double calculate_average(int* p_data, int size);

int main() 
{
    const int NUM_ITEMS = 4;
    int sales_data[NUM_ITEMS] = {150, 220, 180, 300};

    cout << NUM_ITEMS << "日分の売上データが記録されています。\n";

    // 関数を呼び出す方法は、引数が arr[] でも *p でも全く同じ
    double average_sales = calculate_average(sales_data, NUM_ITEMS);

    cout << "\n平均売上は " << average_sales << " です。\n";

    return 0;
}

// 関数の定義
double calculate_average(int* p_data, int size) 
{
    double sum = 0;
    // 受け取ったサイズ情報を使ってループ
    for (int i = 0; i < size; i++) {
        // ポインタ演算で各要素の値にアクセス
        sum += *(p_data + i);
    }

    if (size == 0) {
        return 0;
    }
    return sum / size;
}

コードの解説

  • double calculate_average(int* p_data, int size) 関数の引数を、ポインタp_dataと要素数sizeとして定義しています。
  • calculate_average(sales_data, NUM_ITEMS) 関数を呼び出す側は、引数がint arr[]だろうとint* pだろうと、何も変わりません。配列の名前(=先頭アドレス)と、その要素数を渡すだけです。
  • sum += *(p_data + i); 関数内部では、ポインタ演算*(p_data + i)を使って、配列の各要素にアクセスしています。これはp_data[i]と書いても全く同じ意味になりますが、ここではポインタを引数にしたことを明確にするため、あえてポインタ演算の形で記述しています。

まとめ

今回は、関数にポインタを渡す方法と、それが配列を渡すことと本質的に同じであることを解説しました。

  • 関数の引数において、int arr[]int* pコンパイラにとって同じ意味。どちらもint型へのポインタを受け取る。
  • 書き方の違いは、開発者の意図をどう表現するかのスタイルの違い
  • どちらの記法を使っても、関数側では配列のサイズが分からないという事実は変わらない。
  • 解決策はただ一つ。「配列(ポインタ)と一緒に、その要素数を必ず渡す」こと。

この原則を徹底することで、C++のポインタや配列を引数に持つ関数を、安全かつ再利用性の高い形で設計することができます。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次