配列の終わりがどこにあるかをどうやって知ることができますか?
配列のサイズを個別のパラメーターとして渡さない場合(そうする必要があります)、ある種の番兵値を使用する必要があります(C文字列が文字列の最後の文字の後に0を使用する方法) )。
Cが配列の値を渡せるとは思わないので、配列の最初の要素にポインタを渡すことになっていると思いますが、少しわかりません。
Cの配列セマンティクスは少し注意が必要です。、、、または単項演算子のオペランドである場合、または宣言内の配列を初期化するために使用される文字列リテラルである場合を除き、sizeof
「N要素配列の」タイプの式は「ポインタ」タイプの式に変換されます。に"を指定すると、式の値は配列の最初の要素のアドレスになります。だから、コードを考えると_Alignof
&
T
T
int arr1[10];
foo(arr1); // equivalent to foo(&arr1[0]);
arr1
toの呼び出しの式は、 foo
「の10要素配列からint
」への「ポインタからint
」に変換されます。によって受信される値はfoo
、配列の最初の要素のアドレスです。
void foo(int *a)
{
// do stuff with a[i]
}
式は;a[i]
として解釈されます。次の'番目の要素*(a + i)
のアドレスを見つけ、結果を逆参照します。 i
a
[]
これは、関数の引数に通常の配列であるかのように演算子を 使用するという、長い間言われている方法です。
配列をメイン関数に戻すときに、メモリをクリアせずに結果の関数を返すにはどうすればよいですか?
ここで何を意味するのか正確にはわかりません。次のコードは機能しないことに注意してください。
int *foo(int *a1, int *a2)
{
int a3[SOME_SIZE];
// copy elements from a1 and a2 to a3;
return a3;
}
終了するとfoo
、アレイa3
は存在しなくなります。そのメモリはシステムによって再利用されるため、返すポインタ値は無効になります。3つのオプションがあります。
まず、ターゲット配列を3番目の引数として渡すことができます。
int main(void)
{
int arr1[N];
int arr2[M];
int arr3[K];
...
foo(arr1, arr2, arr3);
...
}
void foo(int *a1, int *a2, int *result) { ... }
見つけたすべての要素を保持するのに十分な大きさの配列を指すという前提条件がありresult
ます(2つのソース配列のうち大きい方と同じ大きさである必要があります)。動的メモリ管理を台無しにしたくない場合は、これが最適な方法です。
次に、関数でターゲット配列を動的に割り当てることができます。
int main(void)
{
int a1[M];
int a2[N];
int *a3;
...
a3 = foo(a1, a2);
...
free(a3);
}
int *foo(int *a1, int *a2)
{
int *result = malloc(sizeof *result * SOME_SIZE);
...
if (element_in_both_arrays())
result[n++] = element_from_both_arrays();
...
return result;
}
使い終わったら、メモリの割り当てを解除することを忘れないでください。
最後に、ターゲット配列をグローバル変数として(つまり、ファイルスコープで)宣言できます。あなたがそれをしたくないので、私は例を提示するつもりはありません。
配列を関数に渡したり、動的に割り当てられたバッファーを返したりするときはいつでも、配列サイズを個別のパラメーターとして渡す必要があります。一般に、ポインタ値だけに基づいて配列に含まれる要素の数を決定することは不可能です。番兵の値を使用できますが、それらは配列の論理サイズのみを示し、物理サイズは示しません。例えば:
char buffer[1024] = "foo";
の論理サイズbuffer
は3(文字列の長さ)ですが、物理サイズは1キロバイトです。