なぜC言語は配列パラメータをポインタとして扱うのか?効率性の観点から解説
なぜC言語は配列パラメータをポインタとして扱うのか?
C言語では、関数へ配列を渡すとき、そのパラメータは自動的にポインタとして扱われます。これは、処理時間を短縮し、プログラムをより効率的に動作させるためです。
仮に配列の各要素のアドレスを1つずつ関数の引数として渡すことも可能ですが、その場合は要素の数だけ処理が必要となり、非常に時間がかかってしまいます。そこでC言語では、配列の先頭要素のアドレス(ベースアドレス)だけを関数に渡す方式が採用されています。先頭アドレスが分かれば、ポインタ演算によって残りのすべての要素へ順番にアクセスできるためです。
実際のところ、次の2つの関数宣言はコンパイラにとってまったく同じ意味を持ちます。
void fun(int a[]) {
...
}
void fun(int *a) { // ポインタ形式。より効率的で意図も明確
...
}
サンプルコード
以下は、配列形式とポインタ形式のどちらでも同じ結果を出力するC言語のサンプルプログラムです。
#include <stdio.h>
void display1(int a[]) /* 配列形式で配列の内容を表示 */
{
int i;
printf("\nCurrent content of the array is: \n");
for(i = 0; i < 5; i++)
printf(" %d", a[i]);
}
void display2(int *a) /* ポインタ形式で配列の内容を表示 */
{
int i;
printf("\nCurrent content of the array is: \n");
for(i = 0; i < 5; i++)
printf(" %d", *(a + i));
}
int main()
{
int a[5] = {4, 2, 7, 9, 6}; /* 配列要素の初期化 */
display1(a);
display2(a);
return 0;
}
実行結果
Current content of the array is: 4 2 7 9 6 Current content of the array is: 4 2 7 9 6
補足:配列の減衰(array decay)について
このように配列名が先頭要素へのポインタへ暗黙的に変換される挙動は、「配列の減衰(array to pointer conversion)」と呼ばれます。sizeof演算子や&演算子を使用する場合など一部の例外を除き、配列名はポインタとして振る舞います。また、関数側でポインタとして受け取った時点では配列のサイズ情報が失われるため、sizeofで要素数を取得できない点には注意が必要です。実務では、要素数を別の引数として一緒に渡すのが一般的な対策となります。
-
C言語で配列が回文かどうかを判定するプログラム
回文とは任意のサイズ n の配列 arr[] が与えられたとき、その配列が回文(パリンドローム)かどうかを判定するのが本記事の目的です。回文とは、前から読んでも後ろから読んでも同じになる並びのことで、MADAM や NAMAN といった文字列が代表的な例として挙げられます。配列が回文かどうかを確認するには、配列を先頭からと末尾から同時に走査し、対応する要素同士を比較していきます。入力例と出力例Input: arr[] = {1, 0, 0, 1} Output: 配列は回文です Input: arr[] = {1, 2, 3, 4, 5} Output: 配列は回文ではありません考え方(アプ
-
C言語で配列内の指定範囲の積(剰余演算)を求める方法
配列 A、範囲の左端 L、右端 R、そして素数 P を入力として与え、L から R までの範囲内にある要素の総乗(積)を P で割った余りを計算して出力するのが本記事の課題です。下図のように、配列の要素が並んでおり、左端の値 L は 2、右端の値 R は 6 です。プログラムはこの範囲内に含まれる要素の積を順次計算していきます。入出力例Input-: A[] = { 1, 2, 3, 4, 5, 6 } P = 29 L = 2 R = 6 Output-: 24 Input-: A[] = {1, 2, 3, 4, 5, 6}, L = 2 R = 5 P = 113