C言語で配列のサイズを決定する方法を教えてください。

C言語で配列のサイズを決定するにはどうすればよいですか?

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

質問へのコメント (1)
ソリューション

要旨:

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]) で、これは配列の 0 番目の要素の大きさです。 これは配列の 0 番目の要素のサイズです。

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

もう一つの利点は,マクロで配列名を簡単にパラメータ化できるようになったことです. を簡単にパラメータ化できるようになったことです。

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

int a[17];
size_t n = NELEMS(a);
解説 (20)

sizeofメソッドは、パラメーターとして受信されない配列を処理する正しい方法です iff 。 関数にパラメーターとして送信された配列はポインターとして扱われるため、「sizeof」は配列ではなくポインターのサイズを返します。

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

テスト:

#include 
#include 

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
解説 (21)

たとえ配列の先頭を指していても、コンパイラにとってはその配列の1つの要素へのポインタと同じなのです。ポインターは、それを初期化するために使用された配列について、他の何も覚えていません。

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

assert(sizeof(a) / sizeof(a[0]) == 10);
assert(sizeof(p) == sizeof(int*));
assert(sizeof(*p) == sizeof(int));
解説 (4)

「トリック」のサイズは私が知っている最良の方法です。1つは小さいですが(私にとって、これは主要なペットのおしっこです)、括 ⁇ の使用における重要な変化です。

ウィキペディアのエントリが明らかにするように、Cの sizeof< / code>関数ではありません。 < strong> operator< / strong>です。 したがって、引数がタイプ名でない限り、引数の周りに括 ⁇ を付ける必要はありません。 これは、引数をキャスト式のように見せ、括 ⁇ も使用するため、覚えやすいです。

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

int myArray[10];

次のようなコードを持つ要素の数を見つけることができます。

size_t n = sizeof myArray / sizeof *myArray;

それは、私にとって、括 ⁇ 付きの代替案よりもはるかに簡単に読めます。 また、インデックス作成よりも簡潔であるため、部門の右側でのアスタリスクの使用も支持します。

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

タイプではなく、実際のオブジェクトがある場合は、常にサイズを使用するのが最善です。そのため、エラーが発生したり、間違ったタイプを示したりすることを心配する必要はありません。

たとえば、ネットワーク全体など、一部のデータをバイトのストリームとして出力する関数があるとします。 関数 send()< / code>を呼び出して、引数として、送信するオブジェクトへのポインターと、オブジェクト内のバイト数を取得させます。 したがって、プロトタイプは次のようになります。

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

次に、整数を送信する必要があるので、次のようにコード化します。

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

これで、 foo< / code>のタイプを指定して、足元を撮影する微妙な方法を導入しました。 2か所。 1つは変更しても、もう1つは変更されない場合、コードは壊れます。 したがって、常に次のようにします。

send(&foo, sizeof foo);

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

解説 (4)
int size = (&arr)[1] - arr;

説明については、[このリンク][1]をチェックしてください。

[1]:http://arjunsreedharan.org/post/69303442896/the-difference-between-arr-and-arr-how-to-find-size "this link"。

解説 (4)

sizeof演算子を使用できますが、ポインターのリファレンスをとるため、関数では機能しません。 配列の長さを見つけるには、次のことができます。

len = sizeof(arr)/sizeof(arr[0])

もともとここで見つかったコード: 配列内の要素の数を見つけるCプログラム

解説 (0)

配列のデータ型がわかっている場合は、次のようなものを使用できます。

int arr[] = {23, 12, 423, 43, 21, 43, 65, 76, 22};

int noofele = sizeof(arr)/sizeof(int);

または、配列のデータ型がわからない場合は、次のようなものを使用できます。

noofele = sizeof(arr)/sizeof(arr[0]);

注:これは、配列が実行時に定義されておらず(mallocなど)、配列が関数に渡されない場合にのみ機能します。 どちらの場合も、「arr」(配列名)はポインターです。

解説 (1)

誰もが利用しているマクロ ARRAYELEMENTCOUNT(x)は、 incorrectlyを評価します。 これは現実的には、「配列」タイプになる表現を持つことができないため、デリケートな問題です。

/* 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」はポインタータイプとして終了し、マクロ全体を無効にします(ポインターパラメーターを持つ関数でマクロを使用しようとした場合と同様)。

結局のところ、この_特定の_インスタンスでは、障害は実際には問題ではありません(そのため、私は皆の時間を無駄にしています。!)、「配列」のタイプを持つ式がないためです。 しかし、実際には、プリプロセッサの評価に関するポイントは、重要なものだと思います。

解説 (3)

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

#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])

等.、無限に。

解説 (0)

Cの配列のサイズ:

int a[10];
size_t size_of_array = sizeof(a);      // Size of array a
int n = sizeof (a) / sizeof (a[0]);    // Number of elements in array a
size_t size_of_element = sizeof(a[0]); // Size of each element in array a                                          
                                       // Size of each element = size of type
解説 (4)
sizeof(array) / sizeof(array[0])
解説 (0)

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

C「ネイティブ」配列はサイズを保存しません。 したがって、配列の長さを個別の変数/ constに保存し、配列を渡すたびに渡すことをお勧めします。

#define MY_ARRAY_LENGTH   15
int myArray[MY_ARRAY_LENGTH];

常にネイティブアレイを避ける必要があります(できない場合は、足を気にしてください)。 C ++を作成している場合は、[STL][1]の「ベクター」コンテナを使用します。 「アレイと比較すると、ほぼ同じパフォーマンスを提供します」と、はるかに便利です。!


// vector is a template, the  means it is a vector of ints
vector 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 
解説 (2)
#define SIZE_OF_ARRAY(_array) (sizeof(_array) / sizeof(_array[0]))
解説 (1)

これを本当に実行して配列の周りを渡したい場合は、配列のタイプへのポインターと配列のサイズを表す整数を格納する構造を実装することをお勧めします。 次に、それを関数に渡すことができます。 配列変数値(ポインターから最初の要素)をそのポインターに割り当てるだけです。 次に、 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 
#include 
/*
#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;
}
解説 (1)

最良の方法は、この情報を、たとえば次のような構造に保存することです。

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

作成、破棄、平等の確認など、必要なすべての機能、および必要なその他すべてを実装します。 パラメータとして渡す方が簡単です。

解説 (1)

関数「sizeof」は、メモリ内の配列で使用されるバイト数を返します。 配列内の要素の数を計算する場合は、その数を配列の「sizeof」変数タイプで割る必要があります。 int array [10];としましょう。コンピューターの変数型整数が32ビット(または4バイト)の場合、配列のサイズを取得するには、次のことを行う必要があります。

int array[10];
int sizeOfArray = sizeof(array)/sizeof(int);
解説 (0)

ここで示す最後の2つのケースである、要素数またはバイトのいずれかで、配列の2つの異なるサイズのいずれかを取得するために、 sizeof(使用できる場合でも)を使用しないことをお勧めします。 2つのサイズのそれぞれについて、以下に示すマクロを使用して、より安全に使用できます。 その理由は、メンテナにコードの意図を明確にし、一見すると「sizeof(arr)」と「sizeof(arr)」の違いを明らかにするためです(この方法で書かれたものは明白ではありません)。コードを読んでいるすべての人。

________

このトピックに関して重要なバグがありました:https://lkml.org/lkml/2015/9/3/428

Linusが提供するソリューションには同意しません。これは、関数のパラメータに配列表記を使用しないことです。

ポインターが配列として使用されているドキュメントとして、配列表記が好きです。 しかし、それはバギーコードを書くことが不可能であるように、誰にでもできるソリューションを適用する必要があることを意味します。

配列には、知りたい3つのサイズがあります。

-配列の要素のサイズ。 -配列内の要素の数。 -配列がメモリで使用するバイト単位のサイズ。

_____

配列の要素のサイズ。

1つ目は非常に単純で、同じように行われるため、配列とポインタのどちらを扱っていてもかまいません。

使用例:

。 void foo(ptrdiff_t nmemb、int arr [static nmemb])。 {。 qsort(arr、nmemb、sizeof(arr [0])、cmp);。 }。

qsort()は、3番目の引数としてこの値を必要とします。

___

質問のトピックである他の2つのサイズについては、配列を処理していることを確認してから、処理しない場合はコンパイルを解除します。ポインターを処理している場合は、値が間違っているためです。 。 コンパイルが壊れたとき。, 39歳だったことが簡単にわかります。;配列を扱います。, 代わりにポインターを使用します。, ポインターの後ろに配列のサイズを格納する変数またはマクロでコードを記述するだけです。

____

配列内の要素の数。

これは最も一般的なものであり、多くの回答が典型的なマクロARRAY_SIZEを提供しています。

``。

ARRAY_SIZE(arr)を定義します(sizeof(arr)/ sizeof(arr)[0]))。

``。

ARRAY_SIZEの結果は、タイプ ptrdiff_tの符号付き変数で一般的に使用されるため、このマクロの符号付きバリアントを定義することをお勧めします。

``。

ARRAY_SSIZE(arr)((ptrdiff_t)ARRAY_SIZE(arr)を定義します。

``。

PTRDIFF_MAXを超えるメンバーを持つ配列は、この署名されたバージョンのマクロに無効な値を与えますが、C17 :: 6.5.6.9を読んで、そのような配列はすでに火で遊んでいます。 これらの場合は、「ARRAY_SIZE」と「size_t」のみを使用してください。

GCC 8などの最近のバージョンのコンパイラーは、このマクロをポインターに適用すると警告が表示されるため、安全です(古いコンパイラーで安全にする他の方法があります)。

これは、配列全体のバイト単位のサイズを各要素のサイズで割ることによって機能します。

使用例:

``。 void foo(ptrdiff_t nmemb)。 {。 char buf [nmemb];。

    fgets(buf、ARRAY_SIZE(buf)、stdin);。

}。

void bar(ptrdiff_t nmemb)。 {。 int arr [nmemb]; .

    (ptrdiff_t i = 0; i< ARRAY_SSIZE(arr); i ++)。
            arr [i] = i; 

}。 ``。

この機能が機能した場合&#39。;t配列を使用します。, 代わりにパラメータとして取得しました。, 以前のコードはコンパイルされません。, したがって、バグを持つことは不可能です。 (最近のコンパイラバージョンが使用されていることを考えると。, または他のトリックが使用されていること。) マクロ呼び出しを値に置き換える必要があります。 ``。 void foo(ptrdiff_t nmemb、char buf [nmemb])。 {。

    fgets(buf、nmemb、stdin);。

}。

void bar(ptrdiff_t nmemb、int arr [nmemb])。 {。

    (ptrdiff_t i = 0; i< nmemb; i ++)。
            arr [i] = i; 

}。 ``。

__

配列がメモリで使用するバイト単位のサイズ。

ARRAY_SIZEは前のケースの解決策として一般的に使用されますが、このケースが安全に記述されることはめったにありません。

この値を取得する一般的な方法は、「sizeof(arr)」を使用することです。 問題:前の問題と同じです。配列の代わりにポインターがある場合、プログラムはおかしくなります。

問題の解決策は、以前と同じマクロを使用することを含みます。これは安全であることがわかっています(ポインターに適用するとコンパイルが中断されます)。

``。

ARRAY_BYTES(arr)を定義します(sizeof((arr)[0])* ARRAY_SIZE(arr))。

``。

動作は非常に簡単です。「ARRAY_SIZE」が行う分割を取り消すため、数学的キャンセルの後、「sizeof(arr)」が1つだけになりますが、「ARRAY_SIZE」構造の安全性が追加されます。

使用例:

``。 void foo(ptrdiff_t nmemb)。 {。 int arr [nmemb]; .

    memset(arr、0、ARRAY_BYTES(arr));。

}。 ``。

memset()は、3番目の引数としてこの値を必要とします。

以前と同様に、配列がパラメーター(ポインター)として受信された場合、配列はコンパイルされず、マクロ呼び出しを値:に置き換える必要があります。

``。 void foo(ptrdiff_t nmemb、int arr [nmemb])。 {。

    memset(arr、0、sizeof(arr [0])* nmemb);。

}。 ``。

解説 (8)

&演算子を使用できます。 これがソースコードです。

#include
#include
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
解説 (4)

最も簡単な答え:

#include 

int main(void) {

    int a[] = {2,3,4,5,4,5,6,78,9,91,435,4,5,76,7,34};//for Example only
    int size;

    size = sizeof(a)/sizeof(a[0]);//Method

    printf ("size = %d",size);
    return 0;
}
解説 (2)
int a[10];
int size = (*(&a+1)-a) ;

詳細については、を参照してください。 ここ。 また、[ここ](https://www.geeksforgeeks.org/how-to-find-size-of-array-in-cc-without-sizeof-operator /)。

解説 (2)