C言語ではローカル変数として宣言した配列の先頭アドレスを関数から返すことはできません. 正確にいえば返すことは可能ですが,関数から抜けた時点でスタックフレーム (stack frame) 上の変数の値は不定になってしまいます. これを回避するには,以下の 3 種類の方法があります.
呼び出し側の関数 (caller) で宣言されたローカル変数は,呼び出し側の関数が終了するまで確保されます.したがって,呼び出され側の関数 (callee) が終了しても変数は不定になりません. また,グローバル変数,もしくは static 記憶クラス指定子をつけて宣言された変数は,静的領域 (static area) に確保されます. 静的領域に確保された変数は,原則的にプログラムの終了時まで確保され続けます.したがって,この場合もまた,呼び出され側の関数が終了しても変数は不定になりません.
以下に関数から配列の先頭アドレスを返すサンプルプログラムを示します.
/* header files */
#include <stdio.h>
#include <stdlib.h>
/* functions */
int *ReturnArray01(int *array);
int *ReturnArray02(void);
int *ReturnArray03(void);
/* global variables */
int g_array[5];
/* main */
int main(void) {
int i;
int array[5];
int *array01;
int *array02;
int *array03;
/* 関数から配列の先頭アドレスを返す */
array01 = ReturnArray01(array);
array02 = ReturnArray02();
array03 = ReturnArray03();
/* 結果を表示 */
printf("array01 array02 array03\n");
printf("------- ------- -------\n");
for ( i = 0; i < 5; i++ ) {
printf("%7d %7d %7d\n",array01[i],array02[i],array03[i]);
}
return EXIT_SUCCESS;
}
/**
* 配列に値をセットする
* @param[in,out] array 配列の先頭アドレス
* @return 配列の先頭アドレス
*/
int *ReturnArray01(int *array) {
int i;
for ( i = 0; i < 5; i++ ) {
array[i] = i + 1;
}
return array;
}
/**
* 配列に値をセットする
* @return 配列の先頭アドレス
*/
int *ReturnArray02(void) {
int i;
static int array[5];
for ( i = 0; i < 5; i++ ) {
array[i] = i + 1;
}
return array;
}
/**
* 配列に値をセットする
* @return 配列の先頭アドレス
*/
int *ReturnArray03(void) {
int i;
for ( i = 0; i < 5; i++ ) {
g_array[i] = i + 1;
}
return g_array;
}
サンプルプログラムの実行結果は以下のようになります.
array01 array02 array03 ------- ------- ------- 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5
たくさんあるC言語関連の書籍の中でも特に役に立った本です.よかったら参考にしてみてください.
C言語の実践的参考書.少々値段は張りますが初心者を脱しようとしている人は絶対に読むべきです.
文法だけでなく,コーディングスタイルやデバッグなど文字通り「実践的」なことが書かれているので非常にためになります.
オライリーの本は,読みにくい本が多いのですが本書はとても読みやすくオススメです.
ポインタの解説書としては最高の書籍です.
この1冊でポインタを完全に理解することができます.全くの初学者が読むには敷居が高いですが,入門書を読み終えた後に読むと非常に有益です.