1247

C で配列のサイズを確認するにはどうすればよいですか?

つまり、配列が保持できる要素の数ですか?

4

23 に答える 23

1530

エグゼクティブサマリー:

int a[17];
size_t n = sizeof(a)/sizeof(a[0]);

完全な答え:

sizeof 配列のサイズをバイト単位で決定するには、次の演算子を使用できます。

int a[17];
size_t n = sizeof(a);

私のコンピューターでは、int は 4 バイトの長さなので、n は 68 です。

配列内の要素の数を決定するには、配列の合計サイズを配列要素のサイズで割ります。次のように、型を使用してこれを行うことができます。

int a[17];
size_t n = sizeof(a) / sizeof(int);

適切な答え (68 / 4 = 17) が a得られますが、 のタイプが変更された場合、 も変更するのを忘れると厄介なバグが発生sizeof(int)します。

したがって、好ましい除数はsizeof(a[0])または同等sizeof(*a)の 、配列の最初の要素のサイズです。

int a[17];
size_t n = sizeof(a) / sizeof(a[0]);

もう 1 つの利点は、マクロで配列名を簡単にパラメーター化し、以下を取得できるようになったことです。

#define NELEMS(x)  (sizeof(x) / sizeof((x)[0]))

int a[17];
size_t n = NELEMS(a);
于 2008-09-01T06:49:44.203 に答える
964

パラメータとして受け取っていない配列を扱っている場合sizeofは、正しい方法です。関数にパラメーターとして送信された配列はポインターとして扱われるため、配列ではなくポインターのサイズを返します。sizeof

したがって、関数内ではこのメソッドは機能しません。size_t size代わりに、配列内の要素数を示す追加のパラメーターを常に渡します。

テスト:

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

void printSizeOf(int intArray[]);
void printLength(int intArray[]);

int main(int argc, char* argv[])
{
    int array[] = { 0, 1, 2, 3, 4, 5, 6 };

    printf("sizeof of array: %d\n", (int) sizeof(array));
    printSizeOf(array);

    printf("Length of array: %d\n", (int)( sizeof(array) / sizeof(array[0]) ));
    printLength(array);
}

void printSizeOf(int intArray[])
{
    printf("sizeof of parameter: %d\n", (int) sizeof(intArray));
}

void printLength(int intArray[])
{
    printf("Length of parameter: %d\n", (int)( sizeof(intArray) / sizeof(intArray[0]) ));
}

出力 (64 ビット Linux OS):

sizeof of array: 28
sizeof of parameter: 8
Length of array: 7
Length of parameter: 2

出力 (32 ビット Windows OS):

sizeof of array: 28
sizeof of parameter: 4
Length of array: 7
Length of parameter: 1
于 2012-04-27T11:14:24.000 に答える
162

ポインターに減衰した配列値を扱う場合は役に立たないことに注意してくださいsizeof。配列の先頭を指していても、コンパイラーにとっては、その配列の単一要素へのポインターと同じです。 . ポインターは、それを初期化するために使用された配列について、それ以外は何も「記憶」しません。

int a[10];
int* p = a;

assert(sizeof(a) / sizeof(a[0]) == 10);
assert(sizeof(p) == sizeof(int*));
assert(sizeof(*p) == sizeof(int));
于 2008-09-01T06:55:23.053 に答える
58

sizeofトリック」は私が知っている最善の方法です。括弧の使用における1つの小さいが(私にとって、これは大きな不満です)重要な変更があります。

ウィキペディアのエントリで明らかなように、Csizeofは関数ではありません。それは演算子です。したがって、引数が型名でない限り、引数を括弧で囲む必要はありません。これは、引数が括弧も使用するキャスト式のように見えるため、覚えやすいです。

だから:あなたが以下を持っている場合:

int myArray[10];

次のようなコードで要素の数を確認できます。

size_t n = sizeof myArray / sizeof *myArray;

私にとっては、括弧付きの代替案よりもはるかに読みやすいです。また、除算の右側にアスタリスクを使用することをお勧めします。インデックスよりも簡潔だからです。

もちろん、これもすべてコンパイル時なので、分割がプログラムのパフォーマンスに影響することを心配する必要はありません。そのため、できる限りこのフォームを使用してください。

型に対してではなく、実際のオブジェクトに対して使用するのが常に最善sizeofです。なぜなら、エラーを起こしたり、間違った型を記述したりすることを心配する必要がないからです。

たとえば、ネットワーク経由などで、データをバイト ストリームとして出力する関数があるとします。関数send()を呼び出して、送信するオブジェクトへのポインタとオブジェクト内のバイト数を引数としてとるようにしましょう。したがって、プロトタイプは次のようになります。

void send(const void *object, size_t size);

次に、整数を送信する必要があるため、次のようにコーディングします。

int foo = 4711;
send(&foo, sizeof (int));

fooここで、 の型を2 か所で指定することで、足元を撃つ巧妙な方法を紹介しました。1 つが変更され、もう 1 つが変更されない場合、コードは壊れます。したがって、常に次のようにします。

send(&foo, sizeof foo);

これで保護されました。確かに、変数の名前を複製しますが、変数を変更すると、コンパイラが検出できる方法で壊れる可能性が高くなります。

于 2008-10-15T10:11:57.340 に答える
42
int size = (&arr)[1] - arr;

説明については、このリンクを参照してください

于 2013-12-07T22:43:01.680 に答える
22

ARRAYELEMENTCOUNT(x)誰もが利用しているマクロは正しく評価されません。「配列」型になる式を使用できないため、これは現実的にはデリケートな問題です。

/* Compile as: CL /P "macro.c" */
# define ARRAYELEMENTCOUNT(x) (sizeof (x) / sizeof (x[0]))

ARRAYELEMENTCOUNT(p + 1);

実際には次のように評価されます。

(sizeof (p + 1) / sizeof (p + 1[0]));

一方

/* Compile as: CL /P "macro.c" */
# define ARRAYELEMENTCOUNT(x) (sizeof (x) / sizeof (x)[0])

ARRAYELEMENTCOUNT(p + 1);

次のように正しく評価されます。

(sizeof (p + 1) / sizeof (p + 1)[0]);

これは、明示的に配列のサイズとはあまり関係がありません。C プリプロセッサがどのように機能するかを正しく観察していないために、多くのエラーが発生していることに気付きました。式が関与する可能性があるのではなく、常にマクロパラメーターをラップします。


正解です; 私の例は悪いものでした。しかし、それは実際に起こるべきことです。前述p + 1したように、最終的にはポインター型になり、マクロ全体が無効になります (ポインター パラメーターを持つ関数でマクロを使用しようとした場合と同様)。

結局のところ、この特定の例では、「配列」型の式がないため、障害はそれほど重要ではありません (つまり、私はみんなの時間を無駄にしているだけです。ハザー!)。しかし、実際には、プリプロセッサ評価の微妙な点が重要だと思います。

于 2014-02-28T01:49:58.257 に答える
18

多次元配列の場合は、少し複雑です。多くの場合、明示的なマクロ定数を定義します。つまり、

#define g_rgDialogRows   2
#define g_rgDialogCols   7

static char const* g_rgDialog[g_rgDialogRows][g_rgDialogCols] =
{
    { " ",  " ",    " ",    " 494", " 210", " Generic Sample Dialog", " " },
    { " 1", " 330", " 174", " 88",  " ",    " OK",        " " },
};

しかし、これらの定数はsizeofを使ってコンパイル時に評価することもできます:

#define rows_of_array(name)       \
    (sizeof(name   ) / sizeof(name[0][0]) / columns_of_array(name))
#define columns_of_array(name)    \
    (sizeof(name[0]) / sizeof(name[0][0]))

static char* g_rgDialog[][7] = { /* ... */ };

assert(   rows_of_array(g_rgDialog) == 2);
assert(columns_of_array(g_rgDialog) == 7);

このコードは C および C++ で機能することに注意してください。2 次元を超える配列の場合は、

sizeof(name[0][0][0])
sizeof(name[0][0][0][0])

など、無限に。

于 2011-08-17T13:21:15.130 に答える
16
sizeof(array) / sizeof(array[0])
于 2008-09-01T06:50:31.253 に答える
13

「あなたは自分の足を撃つ巧妙な方法を導入しました」

C の「ネイティブ」配列は、そのサイズを格納しません。したがって、配列の長さを別の変数/定数に保存し、配列を渡すたびにそれを渡すことをお勧めします。つまり、次のようになります。

#define MY_ARRAY_LENGTH   15
int myArray[MY_ARRAY_LENGTH];

常にネイティブ配列を避ける必要があります (できない場合を除きます。その場合、足を気にしないでください)。C++ を作成している場合は、STLの 'vector' コンテナーを使用します。「配列と比較して、ほとんど同じパフォーマンスを提供します」、そしてそれらははるかに便利です!

// vector is a template, the <int> means it is a vector of ints
vector<int> numbers;  

// push_back() puts a new value at the end (or back) of the vector
for (int i = 0; i < 10; i++)
    numbers.push_back(i);

// Determine the size of the array
cout << numbers.size();

参照: http://www.cplusplus.com/reference/stl/vector/

于 2011-11-14T22:45:48.017 に答える
6

配列を渡すためにこれを本当に実行したい場合は、配列が必要な型へのポインターと配列のサイズを表す整数を格納する構造を実装することをお勧めします。次に、それを関数に渡すことができます。配列変数の値 (最初の要素へのポインター) をそのポインターに割り当てるだけです。次にArray.arr[i]、i 番目の要素Array.sizeを取得し、配列内の要素の数を取得するために使用できます。

私はあなたのためにいくつかのコードを含めました。あまり便利ではありませんが、より多くの機能で拡張できます。正直なところ、これらが必要な場合は、C を使用するのをやめて、これらの機能が組み込まれた別の言語を使用する必要があります。

/* Absolutely no one should use this...
   By the time you're done implementing it you'll wish you just passed around
   an array and size to your functions */
/* This is a static implementation. You can get a dynamic implementation and 
   cut out the array in main by using the stdlib memory allocation methods,
   but it will work much slower since it will store your array on the heap */

#include <stdio.h>
#include <string.h>
/*
#include "MyTypeArray.h"
*/
/* MyTypeArray.h 
#ifndef MYTYPE_ARRAY
#define MYTYPE_ARRAY
*/
typedef struct MyType
{
   int age;
   char name[20];
} MyType;
typedef struct MyTypeArray
{
   int size;
   MyType *arr;
} MyTypeArray;

MyType new_MyType(int age, char *name);
MyTypeArray newMyTypeArray(int size, MyType *first);
/*
#endif
End MyTypeArray.h */

/* MyTypeArray.c */
MyType new_MyType(int age, char *name)
{
   MyType d;
   d.age = age;
   strcpy(d.name, name);
   return d;
}

MyTypeArray new_MyTypeArray(int size, MyType *first)
{
   MyTypeArray d;
   d.size = size;
   d.arr = first;
   return d;
}
/* End MyTypeArray.c */


void print_MyType_names(MyTypeArray d)
{
   int i;
   for (i = 0; i < d.size; i++)
   {
      printf("Name: %s, Age: %d\n", d.arr[i].name, d.arr[i].age);
   }
}

int main()
{
   /* First create an array on the stack to store our elements in.
      Note we could create an empty array with a size instead and
      set the elements later. */
   MyType arr[] = {new_MyType(10, "Sam"), new_MyType(3, "Baxter")};
   /* Now create a "MyTypeArray" which will use the array we just
      created internally. Really it will just store the value of the pointer
      "arr". Here we are manually setting the size. You can use the sizeof
      trick here instead if you're sure it will work with your compiler. */
   MyTypeArray array = new_MyTypeArray(2, arr);
   /* MyTypeArray array = new_MyTypeArray(sizeof(arr)/sizeof(arr[0]), arr); */
   print_MyType_names(array);
   return 0;
}
于 2013-06-13T14:10:29.180 に答える
5

最善の方法は、この情報を構造体などに保存することです。

typedef struct {
     int *array;
     int elements;
} list_s;

create、destroy、check equality など、必要なすべての機能を実装します。パラメータとして渡す方が簡単です。

于 2016-02-17T14:35:27.343 に答える
3

&演算子を使用できます。ソースコードは次のとおりです。

#include<stdio.h>
#include<stdlib.h>
int main(){

    int a[10];

    int *p; 

    printf("%p\n", (void *)a); 
    printf("%p\n", (void *)(&a+1));
    printf("---- diff----\n");
    printf("%zu\n", sizeof(a[0]));
    printf("The size of array a is %zu\n", ((char *)(&a+1)-(char *)a)/(sizeof(a[0])));


    return 0;
};

これが出力例です

1549216672
1549216712
---- diff----
4
The size of array a is 10
于 2013-05-03T08:44:33.987 に答える
2

よりエレガントなソリューションは次のようになります

size_t size = sizeof(a) / sizeof(*a);
于 2020-01-28T10:42:39.893 に答える