8

これは配列サイズを取得するためのマクロです

#define array_size(array) \
(sizeof( array ) / (sizeof( array[0] ) * (sizeof( array ) != sizeof(void*) || sizeof( array[0] ) <= sizeof(void*)))

通常、配列のサイズを取得するには (sizeof( array ) / (sizeof( array[0] )) で十分だと思います。

私はその部分を推測する

(sizeof( array[0] ) * (sizeof( array ) != sizeof(void*) || sizeof( array[0] ) <= sizeof(void*)) 

全体をゼロで割ることを避けることです。誰かが説明するのを助けることができますか?

前もって感謝します。

乾杯、

4

3 に答える 3

12

sizeof array[0]除数に掛ける

(sizeof( array ) != sizeof(void*) || sizeof( array[0] ) <= sizeof(void*))

次の場合は除数をゼロにします

sizeof array == sizeof(void*)

sizeof array[0] > sizeof(void*)

このような場合、コンパイル中にゼロ除算が発生し、コンパイルが失敗する原因になります。

これらのチェックは、ポインターである引数 (配列からポインターへの変換の結果であるかどうかにかかわらず) を検出する試みです。これは、その商を使用してポインターが指す「配列」の大きさを知ることができないためです。

他のポインタ型のサイズが と異なる場合は失敗し、svoid*より大きくないものへのポインタは検出されませんvoid*。それはおそらく、誤った安心感で作者をなだめることによって、利益よりも害を及ぼします.

于 2013-04-25T13:07:44.290 に答える
1

この部分は明らかだと思います:sizeof( array ) / sizeof( array[0] )

この部分(sizeof( array ) != sizeof(void*) || sizeof( array[0] ) <= sizeof(void*))は論理式なので、真か偽かを返します。式全体を計算するとき、論理式を乗算すると、コンパイラは論理式を 0またはsizeof( array[0] )1 に変換します。
sizeof( array ) / (sizeof( array[0] ) * 1)
sizeof( array ) / (sizeof( array[0] ) * 0)

最初のケースは通常の望ましいケースです。2 番目のケースでは、ゼロ除算が原因でコンパイラ エラーが発生します。したがって、たとえば次のように呼び出すと、コードはコンパイルされません。

long *p; // assuming a platform with sizeof(long)==sizeof(void*)
array_size(p);

ただし、次のようなエラーはキャッチされません。

char *p;
array_size(p);

そして、私がコンパイルしたいケースではコンパイルに失敗します:

long x[1]; // assuming a platform with sizeof(long)==sizeof(void*)
array_size(x);

ところで、この関数をマクロとして宣言している場合 (C++ では、テンプレート スタイルのソリューションが本当に好きです)、arrayマクロ内のすべてを に変更する必要があります(array)

于 2013-04-25T13:22:17.780 に答える