web-dev-qa-db-ja.com

渡された配列のCサイズ

可能性のある複製:
sizeof(配列を指すポインタ)を見つける方法)

Sizeof演算子が評価され、コンパイル時に定数に置き換えられることを理解しています。それでは、プログラムのさまざまなポイントでさまざまな配列を渡された関数のサイズをどのように計算できますか?関数にパラメーターとして渡すことはできますが、絶対に必要がない場合は、パラメーターを追加する必要はありません。

これが私が求めていることを説明するための例です:

#include <stdio.h>
#include <stdlib.h>

#define SIZEOF(a) ( sizeof a / sizeof a[0] )


void printarray( double x[], int );

int main()
{
        double array1[ 100 ];


        printf( "The size of array1 = %ld.\n", SIZEOF( array1 ));
        printf( "The size of array1 = %ld.\n", sizeof array1 );
        printf( "The size of array1[0] = %ld.\n\n", sizeof array1[0] );

        printarray( array1, SIZEOF( array1 ) );

        return EXIT_SUCCESS;
}


void printarray( double p[], int s )
{
        int i;


        // THIS IS WHAT DOESN"T WORK, SO AS A CONSEQUENCE, I PASS THE 
        // SIZE IN AS A SECOND PARAMETER, WHICH I'D RATHER NOT DO.
        printf( "The size of p calculated = %ld.\n", SIZEOF( p ));
        printf( "The size of p = %ld.\n", sizeof p );
        printf( "The size of p[0] = %ld.\n", sizeof p[0] );

        for( i = 0; i < s; i++ )
                printf( "Eelement %d = %lf.\n", i, p[i] );

        return;
}
22
Untamed

魔法の解決策はありません。 Cは反映言語ではありません。オブジェクトは、それらが何であるかを自動的に認識しません。

しかし、あなたには多くの選択肢があります:

  1. 明らかに、パラメータを追加します
  2. 呼び出しをマクロで囲み、パラメーターを自動的に追加します
  3. より複雑なオブジェクトを使用します。動的配列と配列のサイズを含む構造を定義します。次に、構造体のアドレスを渡します。
18
DigitalRoss

関数パラメーターが実際に配列型になることはありません。コンパイラが見たとき

_void printarray( double p[], int s )
_

あるいは

_void printarray( double p[100], int s )
_

いずれかに変換します

_void printarray( double* p, int s )
_

したがって、sizeof(p)sizeof(double*)です。はい、サイズをパラメーターとして渡す必要があります。

7
aschepler

問題は、関数が配列値を受信しないことです。ポインタ値を受け取ります。

sizeof演算子または単項&演算子のオペランドである場合、または宣言内の別の配列を初期化するために使用される文字列リテラルである場合を除き、型「array of T "は" pointer to T "型に変換され、その値は配列の最初の要素のアドレスになります。

したがって、printarrayを呼び出すと、array1の型は「doubleの100要素配列」から「doubleへのポインター」に暗黙的に変換されます。したがって、パラメータpのタイプはdouble *であり、double [100]ではありません。

関数パラメーター宣言のコンテキストでは、T a[]T *aと同じです。

これが、配列のサイズを個別に渡す必要がある理由です。

5
John Bode

あなた自身の質問に答えました。それはコンパイル時に計算されるので、実行時に「sizeof p」はどのようにして複数の値を持つことができますか?

長さをパラメーターとして渡すことは良い解決策です。そうでない場合は、配列が常に特別な値(文字列やnullバイトなど)で終わるようにすることができます。

1
bobDevil

文字列の処理方法であるセンチネル値を使用できます。欠点は、配列のサイズを見つけるために配列全体を反復処理する必要があることです。

たとえば、次のような文字列があるとします。

char s1[] = "foobar";

実際に持っているのは長さ7の配列で、7番目のスポットは配列/文字列の終わりを示すのに役立つヌル終了文字 '\ 0'です。

あなたがそれを行うことができる別の方法は、配列とそれに続くサイズで構成される構造体を作成することです。

0

あなたはどちらかでなければなりません

  1. 配列のサイズをパラメータとして関数に渡します
  2. 配列が既知の値で終わっていることを確認し、その値に達したら停止します。
0
Scott Duckworth

配列がnullで終了している場合は、配列を反復処理して最後の値を見つけることができます。 Cの多くの文字列演算子はそのように機能します

そうでなければ、あなたはあまり選択肢がありません。

sizeofはpのサイズを返します。これはポインターであり、intサイズと等しくなります。

0
Eric