web-dev-qa-db-ja.com

sizeof演算子の実装

Sizeof演算子を実装しようとしました。このようにしています。

#define my_sizeof(x) ((&x + 1) - &x)

しかし、どちらのデータ型でも結果は常に「1」になります。

私はそれのためにそれをググった..そして私はコードを見つけたtypecasted

#define my_size(x) ((char *)(&x + 1) - (char *)&x)

そして、コードが型キャストされている場合、コードは機能します。理由はわかりません。

それはまた働いています

#define my_sizeof(x) (unsigned int)(&x + 1) - (unsigned int)(&x)

型キャストされた場合と型キャストされなかった場合の動作を誰かが説明できますか?

前もって感謝します..

23

ポインター減算の結果は、バイトではなくelementsにあります。したがって、最初の式は、定義により_1_に評価されます。

これはさておき、マクロでは括弧を使うべきです:

_#define my_sizeof(x) ((&x + 1) - &x)
#define my_sizeof(x) ((char *)(&x + 1) - (char *)&x)
_

そうしないと、式でmy_sizeof()を使用しようとするとエラーが発生する可能性があります。

29
NPE

sizeof演算子はC(およびC++)言語仕様の一部であり、コンパイラー(フロントエンド)内に実装されています。他のC構文で実装する方法はありません( typeof のようなGCC拡張機能を使用しない限り)。これは、副作用を起こすことなく、型または式をオペランドとして受け入れることができるためです(例:sizeof((i>1)?i:(1/i))はクラッシュしませんi==0がマクロmy_sizeofはゼロ除算でクラッシュします)。 Cコーディングのガイドライン 、および wikipedia も参照してください。

C ポインタ演算 を理解する必要があります。たとえば、 この質問 。ポインタの違いは、バイトではなく要素で表現されます。

#define my_sizeof(x) ((char *)(&x + 1) - (char *)&x)

このmy_sizeof()マクロは、次の場合には機能しません。

  1. sizeof 1-4バイト(4バイトのintのプラットフォームの場合)
    my_sizeof(1)-まったくコンパイルされません。

  2. sizeof (int)-4バイト(4バイトのプラットフォームの場合int
    my_sizeof(int)-コードをまったくコンパイルしません。

変数に対してのみ機能します。 intfloatcharなどのデータ型、23.4'A'などのリテラル、またはa+bなどの右辺値式では機能しません。またはfoo()

7
Kuppappa DH

しかし、いずれのデータ型でも常に結果は「1」となる

はい、それがポインター演算の仕組みです。ポイントされているタイプの単位で機能します。したがって、char *にキャストすると、charの単位が機能します。

6
_#define my_sizeof(x) ((&x + 1) - &x)
_

_&x_は、プログラムで宣言された変数(double xとしましょう)のアドレスを与え、1でインクリメントすると、タイプxの次の変数を格納できるアドレスを与えます(ここではaddr_of(x) + 8、 doubleのサイズは8バイトです)。

違いは、xのタイプの変数をいくつのメモリに格納できるかという結果を与えます。これは、タイプxに対して明らかに1になります(1でインクリメントし、その差を取ることは、完了)。

_#define my_size(x) ((char *)(&x + 1) - (char *)&x)
_

それを_char*_に型キャストし、その差をとると、指定されたメモリ空間に格納できるchar型の変数の数(差)がわかります。各charは1バイトのメモリしか必要としないため、(メモリの量)/ 1は、マクロに渡される変数のタイプの連続する2つのメモリ位置間のバイト数、したがってメモリの量を示しますタイプxの変数に必要です。

しかし、このマクロにリテラルを渡してそのサイズを知ることはできません。

5
roottraveller

私は昨日これを検索し、このマクロを見つけました:

#define mysizeof(X)  ((X*)0+1)

これは、Xを1回だけ展開し(x ++のような式の二重評価としてエラーは発生しません)、現在まで問題なく機能します。

0
C.Y