C言語の素人である筆者は,「きっと配列の大きさを決めていないのが良くないのだろう」と思い,配列の要素数を決めて再度コンパイルに挑戦してみた.やはり,
char[256] sub( char a[], char b[] )に対し,宣言が間違えているとコンパイラがエラーを出す.関数には基本型変数(スカラ変数=単一の値しか保持できない変数)しか,値を返さないようである.関数に型はあるが,変数の型を全部許している訳ではなさそうである.
(ここが変だよC言語〈上〉, pp.101-102)
説明はその通りなのですが,関数の宣言のしかたが,Cらしくありません.Javaのようです.Javaでも,こういう戻り値の型を持つメソッドは,見たことがないのですが.
Cっぽく書くなら,
char sub( char a[], char b[] )[]
や
char sub( char a[], char b[] )[256]
のような.まあこれらでも,ダメなものはダメでno still means no,理由は,上の引用の通りです.
とはいえ,引数の後ろに配列の [ ] が来て,文法的に正しいような書き方も,できます.
『C言語によるプログラミング―スーパーリファレンス編』のp.81に,「配列を指すポインタを返す関数」として,int (*a(double))[2] という例があります.これは,引数はdouble型で,戻り値はint (*)[2]型となるような関数型の識別子aを表しています.
コードを書いてみますかね.
#include <stdio.h> #include <math.h> #define DIVISION 36 /* 1周を刻む数 */ #define ANGLE_INIT 1 /* 初期角(ラジアン) */ /* http://www2s.biglobe.ne.jp/~nuts/labo/inti/inti09.html より */ #ifndef M_PI #define M_PI 3.14159265358979323846 #endif int (*a(double))[2]; /* ここで実現! */ int main(void) { int (*y)[2] = a(ANGLE_INIT); int i; for (i = 0; i < DIVISION; i++) { printf("y[%2d][0] = %5d, ", i, y[i][0]); printf("y[%2d][1] = %5d\n", i, y[i][1]); } return 0; } int (*a(double d))[2] { static int x[DIVISION][2]; int i; for (i = 0; i < DIVISION; i++) { double ang = d + (double)i / DIVISION * 2 * M_PI; x[i][0] = sin(ang) * 1000; x[i][1] = cos(ang) * 1000; } return x; }
マクロANGLE_INITの角度(単位はラジアン)を起点として,10度(すみませんがここは度数法で)刻みで36個の角度のサインとコサインを1000倍にした値を求めます.