C言語で配列のサイズを決定する方法を教えてください。
C言語で配列のサイズを決定するにはどうすればよいですか?
つまり、配列が保持できる要素数は?
894
20
C言語で配列のサイズを決定するにはどうすればよいですか?
つまり、配列が保持できる要素数は?
要旨:
完全な答え:。
配列のサイズをバイト単位で決定するには、
sizeof
演算子を使用します。 演算子を使用します。私のコンピュータでは、intは4バイト長なので、nは68です。
配列の要素数を求めるには、配列の総サイズを配列要素のサイズで割ればよい。 を配列の要素の大きさで割ればよいのです。 このように型を使ってやることもできます。
のように型を変えてやれば、正しい答え (68 / 4 = 17) が得られますが、もし a
の型が変わった場合、
sizeof(int)` も変更するのを忘れると厄介なバグが発生します。 を変更し忘れると、厄介なバグが発生します。そこで、望ましい除数は
sizeof(a[0])
で、これは配列の 0 番目の要素の大きさです。 これは配列の 0 番目の要素のサイズです。もう一つの利点は,マクロで配列名を簡単にパラメータ化できるようになったことです. を簡単にパラメータ化できるようになったことです。
sizeof
メソッドは、パラメーターとして受信されない配列を処理する正しい方法です iff 。 関数にパラメーターとして送信された配列はポインターとして扱われるため、「sizeof」は配列ではなくポインターのサイズを返します。したがって、内部関数ではこのメソッドは機能しません。 代わりに、配列内の要素の数を示す追加のパラメーター「size_t size」を常に渡します。
テスト:
出力(64ビットLinux OS):
出力(32ビットWindows OS):
たとえ配列の先頭を指していても、コンパイラにとってはその配列の1つの要素へのポインタと同じなのです。ポインターは、それを初期化するために使用された配列について、他の何も覚えていません。
「トリック」のサイズは私が知っている最良の方法です。1つは小さいですが(私にとって、これは主要なペットのおしっこです)、括 ⁇ の使用における重要な変化です。
ウィキペディアのエントリが明らかにするように、Cの
sizeof< / code>関数ではありません。 < strong> operator< / strong>です。 したがって、引数がタイプ名でない限り、引数の周りに括 ⁇ を付ける必要はありません。 これは、引数をキャスト式のように見せ、括 ⁇ も使用するため、覚えやすいです。
だから:あなたが以下を持っているなら:
次のようなコードを持つ要素の数を見つけることができます。
それは、私にとって、括 ⁇ 付きの代替案よりもはるかに簡単に読めます。 また、インデックス作成よりも簡潔であるため、部門の右側でのアスタリスクの使用も支持します。
もちろん、これもすべてコンパイル時なので、分割がプログラムのパフォーマンスに影響を与えることを心配する必要はありません。 できる限りこのフォームを使用してください。
タイプではなく、実際のオブジェクトがある場合は、常にサイズを使用するのが最善です。そのため、エラーが発生したり、間違ったタイプを示したりすることを心配する必要はありません。
たとえば、ネットワーク全体など、一部のデータをバイトのストリームとして出力する関数があるとします。 関数
send()< / code>を呼び出して、引数として、送信するオブジェクトへのポインターと、オブジェクト内のバイト数を取得させます。 したがって、プロトタイプは次のようになります。
次に、整数を送信する必要があるので、次のようにコード化します。
これで、
foo< / code>のタイプを指定して、足元を撮影する微妙な方法を導入しました。 2か所。 1つは変更しても、もう1つは変更されない場合、コードは壊れます。 したがって、常に次のようにします。
今、あなたは保護されています。 確かに、変数の名前を複製しますが、変更すると、コンパイラが検出できる方法で破損する可能性が高くなります。
説明については、[このリンク][1]をチェックしてください。
[1]:http://arjunsreedharan.org/post/69303442896/the-difference-between-arr-and-arr-how-to-find-size "this link"。
sizeof演算子を使用できますが、ポインターのリファレンスをとるため、関数では機能しません。 配列の長さを見つけるには、次のことができます。
もともとここで見つかったコード: 配列内の要素の数を見つけるCプログラム。
配列のデータ型がわかっている場合は、次のようなものを使用できます。
または、配列のデータ型がわからない場合は、次のようなものを使用できます。
注:これは、配列が実行時に定義されておらず(mallocなど)、配列が関数に渡されない場合にのみ機能します。 どちらの場合も、「arr」(配列名)はポインターです。
誰もが利用しているマクロ
ARRAYELEMENTCOUNT(x)
は、 incorrectlyを評価します。 これは現実的には、「配列」タイプになる表現を持つことができないため、デリケートな問題です。_実際_は次のように評価されます。
一方。
それは正しく評価します:
これは、配列のサイズとは明確に関係がありません。 Cプリプロセッサがどのように機能するかを真に観察しないことによる多くのエラーに気づきました。 常にマクロパラメータをラップしますが、式は関与しない可能性があります。
これは正しいです。私の例は悪いものでした。 しかし、それは実際に起こるべきことです。 前述のように、「p + 1」はポインタータイプとして終了し、マクロ全体を無効にします(ポインターパラメーターを持つ関数でマクロを使用しようとした場合と同様)。
結局のところ、この_特定の_インスタンスでは、障害は実際には問題ではありません(そのため、私は皆の時間を無駄にしています。!)、「配列」のタイプを持つ式がないためです。 しかし、実際には、プリプロセッサの評価に関するポイントは、重要なものだと思います。
多次元配列の場合、少し複雑です。 多くの場合、人々は明示的なマクロ定数を定義します。
ただし、これらの定数は sizeof :を使用してコンパイル時にも評価できます。
このコードはCおよびC ++で動作することに注意してください。 2次元を超える配列の場合。
等.、無限に。
Cの配列のサイズ:
「あなたは自分の足を撃つ微妙な方法を導入しました」。
C「ネイティブ」配列はサイズを保存しません。 したがって、配列の長さを個別の変数/ constに保存し、配列を渡すたびに渡すことをお勧めします。
常にネイティブアレイを避ける必要があります(できない場合は、足を気にしてください)。 C ++を作成している場合は、[STL][1]の「ベクター」コンテナを使用します。 「アレイと比較すると、ほぼ同じパフォーマンスを提供します」と、はるかに便利です。!
これを本当に実行して配列の周りを渡したい場合は、配列のタイプへのポインターと配列のサイズを表す整数を格納する構造を実装することをお勧めします。 次に、それを関数に渡すことができます。 配列変数値(ポインターから最初の要素)をそのポインターに割り当てるだけです。 次に、
Array.arr [i]
に移動してi番目の要素を取得し、Array.size
を使用して配列内の要素の数を取得できます。コードを含めました。 それほど便利ではありませんが、より多くの機能でそれを拡張できます。 ただし、正直なところ、これらが必要な場合は、Cの使用を中止し、これらの機能が組み込まれた別の言語を使用する必要があります。
最良の方法は、この情報を、たとえば次のような構造に保存することです。
作成、破棄、平等の確認など、必要なすべての機能、および必要なその他すべてを実装します。 パラメータとして渡す方が簡単です。
関数「sizeof」は、メモリ内の配列で使用されるバイト数を返します。 配列内の要素の数を計算する場合は、その数を配列の「sizeof」変数タイプで割る必要があります。
int array [10];
としましょう。コンピューターの変数型整数が32ビット(または4バイト)の場合、配列のサイズを取得するには、次のことを行う必要があります。ここで示す最後の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];。
}。
void bar(ptrdiff_t nmemb)。 {。 int arr [nmemb]; .
}。 ``。
この機能が機能した場合'。;t配列を使用します。, 代わりにパラメータとして取得しました。, 以前のコードはコンパイルされません。, したがって、バグを持つことは不可能です。 (最近のコンパイラバージョンが使用されていることを考えると。, または他のトリックが使用されていること。) マクロ呼び出しを値に置き換える必要があります。 ``。 void foo(ptrdiff_t nmemb、char buf [nmemb])。 {。
}。
void bar(ptrdiff_t nmemb、int arr [nmemb])。 {。
}。 ``。
__。
配列がメモリで使用するバイト単位のサイズ。
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()
は、3番目の引数としてこの値を必要とします。以前と同様に、配列がパラメーター(ポインター)として受信された場合、配列はコンパイルされず、マクロ呼び出しを値:に置き換える必要があります。
``。 void foo(ptrdiff_t nmemb、int arr [nmemb])。 {。
}。 ``。
&
演算子を使用できます。 これがソースコードです。これがサンプル出力です。
最も簡単な答え:
詳細については、を参照してください。 ここ。 また、[ここ](https://www.geeksforgeeks.org/how-to-find-size-of-array-in-cc-without-sizeof-operator /)。