2

私は比較する小さなプログラムを持っています

(1)sizeof、(2)numeric_limits :: Digits、(3)およびループの結果

C++実装の「int型」のサイズに関してすべてが同じことを報告するようにするためです。ただし、sizeofの内部についてはわからないため、numeric_limits::digitsを報告しているだけなのかどうか疑問に思う必要があります。ありがとう

4

3 に答える 3

3

ほとんどsizeof()のコンパイラでは、コンパイラが内部型テーブルで指定された型 (またはオブジェクトの型) を検索し、その型の定義されたサイズのリテラルを生成するコードに挿入します。これは、実行時ではなくコンパイル時に発生します。

コメントの質問に答えるために、C++ のコンパイラの内部への言語定義のアクセスはありません (sizeof()もちろん、それ自体のようなものの外では)。私が知っている唯一の同様の言語で、そのようなことができるのは Ada だけです。Ada は、コンパイラに依存しないコード分析ツールを作成するためのASISを提供します。

于 2011-05-16T20:52:53.080 に答える
1

sizeof演算子は、指定された型のインスタンスがメモリ内で占有するサイズ (バイト単位) をコンパイラが報告するコンパイル時の構造です 。

すべてのコンパイラの実装に固有であるため、一般的な「これがsizeofの仕組みです」という答えを出すのは困難です。一般的には、型のすべてのフィールドのサイズを計算し、アライメントを考慮しながらそれらを合計することで機能します。

たとえば、妥当な出力のセットは次のとおりです [1]。

struct S1 {
  int field1;
  int field2;
};

struct S2 {
  int field1;
  bool field2;
  int field3;
}

sizeof(S1) == 8
sizeof(S2) == 12;

多くのコンパイラが のサイズを 9 ではなく 12 と報告する理由は、アラインメントの問題を考慮し、3 バイトを挿入してとS2の間のギャップを補う必要があるためです。field2field3

[1] 注: 私は合理的で保証されていないと言いました:)。C コンパイルにはサイズの柔軟性があり、使用しているコンパイラを知らずにサイズに関する詳細を述べるのはほぼ不可能です。

于 2011-05-16T20:48:39.970 に答える
0

の内部構造はあまりありませんsizeof。これは、オペランド (式または型) のサイズをバイト単位で報告する組み込み演算子です。

あなたのコードはかなり複雑です-そして、使用typeidすると不思議に思います...

次のような回答を生成するバイリンガル プログラム (C++ の C サブセットで記述) があります。

 1 = sizeof(char)
 1 = sizeof(unsigned char)
 2 = sizeof(short)
 2 = sizeof(unsigned short)
 4 = sizeof(int)
 4 = sizeof(unsigned int)
 8 = sizeof(long)
 8 = sizeof(unsigned long)
 4 = sizeof(float)
 8 = sizeof(double)
16 = sizeof(long double)
 8 = sizeof(size_t)
 8 = sizeof(ptrdiff_t)
 8 = sizeof(time_t)
 8 = sizeof(void *)
 8 = sizeof(char *)
 8 = sizeof(short *)
 8 = sizeof(int *)
 8 = sizeof(long *)
 8 = sizeof(float *)
 8 = sizeof(double *)
 8 = sizeof(int (*)(void))
 8 = sizeof(double (*)(void))
 8 = sizeof(char *(*)(void))
 1 = sizeof(struct { char a; })
 2 = sizeof(struct { short a; })
 4 = sizeof(struct { int a; })
 8 = sizeof(struct { long a; })
 4 = sizeof(struct { float a; })
 8 = sizeof(struct { double a; })
16 = sizeof(struct { char a; double b; })
16 = sizeof(struct { short a; double b; })
16 = sizeof(struct { long a; double b; })
 4 = sizeof(struct { char a; char b; short c; })
16 = sizeof(struct { char a; char b; long c; })
 4 = sizeof(struct { short a; short b; })
 6 = sizeof(struct { char a[3]; char b[3]; })
 8 = sizeof(struct { char a[3]; char b[3]; short c; })
16 = sizeof(struct { long double a; })
32 = sizeof(struct { char a; long double b; })

(これは、MacOS X 10.6.7 上の G++ 4.6.0 によって生成されました - 64 ビット コンパイル)。私が使用したコードは次のとおりです。

#ifdef __cplusplus
#define __STDC_CONSTANT_MACROS
#endif /* __cplusplus */

#include <stdio.h>
#include <time.h>
#include <stddef.h>
#if __STDC_VERSION__ >= 199901L || HAVE_INTTYPES_H
#include <inttypes.h>
#endif /* __STDC_VERSION__ */

/* Using the simple C code in SPRINT() for structures leads to complaints from G++ */
/* Using the code in TPRINT() for pointers to functions leads to other complaints */
#define TPRINT(x)   do { typedef x y; printf("%2u = sizeof(" #x ")\n", (unsigned int)sizeof(y)); } while (0)
#define SPRINT(x)   printf("%2u = sizeof(" #x ")\n", (unsigned int)sizeof(x))

int main(void)
{
    /* Basic Types */
    SPRINT(char);
    SPRINT(unsigned char);
    SPRINT(short);
    SPRINT(unsigned short);
    SPRINT(int);
    SPRINT(unsigned int);
    SPRINT(long);
    SPRINT(unsigned long);

    SPRINT(float);
    SPRINT(double);
    SPRINT(long double);
    SPRINT(size_t);
    SPRINT(ptrdiff_t);
    SPRINT(time_t);

    /* Fancy integers */
#if __STDC_VERSION__ >= 199901L || HAVE_LONG_LONG
    SPRINT(long long);
    SPRINT(unsigned long long);
#endif /* __STDC_VERSION__ || HAVE_LONG_LONG */
#if __STDC_VERSION__ >= 199901L || HAVE_INTTYPES_H
    SPRINT(uintmax_t);
#ifdef INT8_MAX
    SPRINT(int8_t);
#endif
#ifdef INT16_MAX
    SPRINT(int16_t);
#endif
#ifdef INT32_MAX
    SPRINT(int32_t);
#endif
#ifdef INT64_MAX
    SPRINT(int64_t);
#endif
#ifdef INT128_MAX
    SPRINT(int128_t);
#endif
    SPRINT(int_least8_t);
    SPRINT(int_least16_t);
    SPRINT(int_least32_t);
    SPRINT(int_least64_t);
    SPRINT(int_fast8_t);
    SPRINT(int_fast16_t);
    SPRINT(int_fast32_t);
    SPRINT(int_fast64_t);
    SPRINT(uintptr_t);
#endif /* __STDC_VERSION__ || HAVE_INTTYPES_H */

    /* Pointers */
    SPRINT(void *);
    SPRINT(char *);
    SPRINT(short *);
    SPRINT(int *);
    SPRINT(long *);
    SPRINT(float *);
    SPRINT(double *);

    /* Pointers to functions */
    SPRINT(int (*)(void));
    SPRINT(double (*)(void));
    SPRINT(char *(*)(void));

    /* Structures */
    TPRINT(struct { char a; });
    TPRINT(struct { short a; });
    TPRINT(struct { int a; });
    TPRINT(struct { long a; });
    TPRINT(struct { float a; });
    TPRINT(struct { double a; });
    TPRINT(struct { char a; double b; });
    TPRINT(struct { short a; double b; });
    TPRINT(struct { long a; double b; });
    TPRINT(struct { char a; char b; short c; });
    TPRINT(struct { char a; char b; long c; });
    TPRINT(struct { short a; short b; });
    TPRINT(struct { char a[3]; char b[3]; });
    TPRINT(struct { char a[3]; char b[3]; short c; });
    TPRINT(struct { long double a; });
    TPRINT(struct { char a; long double b; });
#if __STDC_VERSION__ >= 199901L || HAVE_LONG_LONG
    TPRINT(struct { char a; long long b; });
#endif /* __STDC_VERSION__ */
#if __STDC_VERSION__ >= 199901L || HAVE_INTTYPES_H
    TPRINT(struct { char a; uintmax_t b; });
#endif /* __STDC_VERSION__ || HAVE_INTTYPES_H */

    return(0);
}

__STDC_CONSTANT_MACROSなぜand SPRINT()vsをいじらなければならなかったのか正確には覚えていませんがTPRINT()、コードをバイリンガルにするために (2010 年 3 月に) 必要だったようです。

于 2011-05-16T20:56:07.030 に答える