2

我有一个小程序比较

(1) sizeof, (2) numeric_limits::digits, (3) 和循环的结果

为了确保它们在任何 C++ 实现上都报告有关“int 类型”大小的相同内容。但是因为我不了解 sizeof 的内部结构,所以我不得不怀疑它是否只是在报告 numeric_limits::digits。谢谢

4

3 回答 3

3

大多数编译器最有可能sizeof()导致编译器在其内部类型表中查找给定类型(或对象的类型),并将该类型定义大小的文字插入到它生成的代码中。这将发生在编译时,而不是运行时。

要回答评论中的问题,C++ 中没有任何语言定义的对编译器内部的访问(sizeof()当然,除了它本身之外)。我所知道的唯一一种类似的语言可以让你做类似的事情是 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;

许多编译器将大小报告S2为 12 而不是 9 的原因是它必须考虑对齐问题,因此插入 3 个字节来弥补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; })

(这是由 G++ 4.6.0 在 MacOS X 10.6.7 上生成的 - 一个 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_MACROSand SPRINT()vs TPRINT(),但这似乎是使代码双语所需要的(早在 2010 年 3 月)。

于 2011-05-16T20:56:07.030 回答