问题
I have a small program which compares
(1) sizeof, (2) numeric_limits::digits, (3) and the results of a loop
in an effort to make sure they all report the same thing regarding the size of the "int types" on any C++ implementation. However because I don't know about the internals of sizeof, I have to wonder if it is just reporting numeric_limits::digits. Thanks
回答1:
Most likely sizeof()
on most compilers causes the compiler to look the given type (or object's type) up in its internal type table and insert a literal for that type's defined size into the code it generates. This would happen at compile time, not runtime.
To answer the question in the comments, there isn't any language-defined access to the compiler's internals in C++ (outside of things like sizeof()
itself, of course). The only similar language I know of that lets you do stuff like that is Ada, which provides ASIS for writing compiler-independent code analysis tools.
回答2:
The sizeof
operator is a compile time construct by which the compiler reports the size, in bytes, that an instance of the given type will occupy in memory.
It's hard to give a general "this is how sizeof works" answer because it's specific to every compiler implementation. In general though it works by computing the size of every field of a type and adding them together while accounting for alignment.
For example here's a reasonable set of outputs [1]
struct S1 {
int field1;
int field2;
};
struct S2 {
int field1;
bool field2;
int field3;
}
sizeof(S1) == 8
sizeof(S2) == 12;
The reason many compilers will report the size of S2
as 12 as opposed to 9 is that it must account for alignment issues and hence insert 3 bytes to make up for the gap between field2
and field3
[1] Note: I said reasonable not guaranteed :). C compiles have a lot of flexibility in sizes and it's nearly impossible to state specifics about sizes without knowing the compiler you're working with
回答3:
There aren't many internals to sizeof
; it is a built-in operator which reports the size of its operand (either an expression or a type) in bytes.
Your code is rather complex - and using typeid
leaves me wondering...
I have a bilingual program (written in the C subset of C++) that produces answers such as:
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; })
(This was produced by G++ 4.6.0 on MacOS X 10.6.7 - a 64-bit compilation). The code I used is:
#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);
}
I don't remember exactly why I had to do the messing with __STDC_CONSTANT_MACROS
and SPRINT()
vs TPRINT()
, but that seemed to be what was needed (back in March 2010) to make the code bilingual.
来源:https://stackoverflow.com/questions/6023195/how-does-sizeof-work-for-int-types