可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
How can I print the result of sizeof() at compile time in C?
For now I am using a static assert (home brewed based on other web resources) to compare the sizeof() result to various constants. While this works... it is far from elegant or fast. I can also create an instance of the variable/struct and look in the map file but this is also less elegant and fast than a direct call/command/operator. Further, this is an embedded project using multiple cross-compilers... so building and loading a sample program to the target and then reading out a value is even more of a hassle than either of the above.
In my case (old GCC), #warning sizeof(MyStruct)
does not actually interpret sizeof() before printing the warning.
回答1:
I was mucking around looking for similar functionality when I stumbled on this:
Is it possible to print out the size of a C++ class at compile-time?
Which gave me the idea for this:
char (*__kaboom)[sizeof( YourTypeHere )] = 1
Which results in the following warning in VS2015:
warning C4047: 'initializing': 'DWORD (*)[88]' differs in levels of indirection from 'int'
Where 88 in this case would be the size you're looking for.
Super hacky, but it does the trick. Probably a couple years too late, but hopefully this will be useful to someone.
I haven't had a chance to try with gcc or clang yet, but I'll try to confirm whether or not it works if someone doesn't get to it before me.
Edit: Works out of the box for clang 3.6
The only trick I could get to work for GCC was abusing -Wformat and having the macro define a function like the following:
void kaboom_print( void ) { printf( "%d", __kaboom" ); }
Which will give you a warning like:
...blah blah blah... argument 2 has type 'char (*)[88]'
Slightly more gross than the original suggestion, but maybe someone who knows gcc a bit better can think of a better warning to abuse.
回答2:
All you need is a trick that causes the compiler to complain about some compile time integer values being used incorrectly, like duplicated case
constant:
struct X { int a,b; int c[10]; }; int _tmain(int argc, _TCHAR* argv[]) { int dummy; switch (dummy) { case sizeof(X): case sizeof(X): break; } return 0; }
------ Build started: Project: cpptest, Configuration: Debug Win32 ------ cpptest.cpp c:\work\cpptest\cpptest\cpptest.cpp(29): error C2196: case value '48' already used ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
So sizeof the struct X is 48
回答3:
I stumbled upon a solution similar to Bakhazard's great solution, and this one produces a much less verbose warning, so you may find it useful:
char (*__fail)(void)[sizeof(uint64_t)] = 1;
This produces the error message
Function cannot return array type 'char [8]'
This was tested with the latest version of clang(1)
.
回答4:
You can't do this, not with structures. The preprocessor is invoked before compilation takes place, so there isn't even the concept of structure; you can't evaluate the size of something that doesn't exist / wasn't defined. The preprocessor does tokenize a translation unit, but it does so only for the purpose of locating macro invocation.
The closest thing you can have is to rely on some implementation-defined macros that evaluate to the size of built-in types. In gcc, you can find those with:
gcc -dM -E - /null | grep -i size
Which in my system printed:
#define __SIZE_MAX__ 18446744073709551615UL #define __SIZEOF_INT__ 4 #define __SIZEOF_POINTER__ 8 #define __SIZEOF_LONG__ 8 #define __SIZEOF_LONG_DOUBLE__ 16 #define __SIZEOF_SIZE_T__ 8 #define __SIZEOF_WINT_T__ 4 #define __SIZE_TYPE__ long unsigned int #define __SIZEOF_PTRDIFF_T__ 8 #define __SIZEOF_FLOAT__ 4 #define __SIZEOF_SHORT__ 2 #define __SIZEOF_INT128__ 16 #define __SIZEOF_WCHAR_T__ 4 #define __SIZEOF_DOUBLE__ 8 #define __SIZEOF_LONG_LONG__ 8
There is really nothing you can do to know the size of a custom struct without writing a program and executing it.