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() re
Though this isn't exactly at compile time, it is before runtime, so it could still be relevant for some people.
You can define an array like so:
uint8_t __some_distinct_name[sizeof(YourTypeHere)];
And then, after compilation, get the size from the object file:
$ nm -td -S your_object_file | # list symbols and their sizes, in decimal
grep ' __some_distinct_name$' | # select the right one
cut -d' ' -f2 | # grab the size field
xargs printf "Your type is %d B\n" # print
Duplicate case
constant is a trick that is guaranteed to work IN ALL C COMPILERS regardless of how each of them reports error. For Visual C++, it is simple:
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;
}
Compilation result:
------ 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
EDITED (3jun2020): For gcc or any other compilers that only print "duplicate case value", I use this trick to narrow down the value:
1) add a case value 1==2 (to represent false)
2) by trial and error, narrow down the value e.g. I try to guess the sizeof(X)
is >16:
#include <stdio.h>
typedef struct _X {
int a;
char b[10];
} X;
int main()
{
printf("Hello World");
int dummy=0 ;
switch (dummy) {
case 1==2:
case sizeof( X)>16:
//case 16:
break;
}
return 0;
}
result:
main.c: In function ‘main’:
main.c:14:5: error: duplicate case value
case sizeof( X)>16:
^~~~
main.c:13:5: error: previously used here
case 1==2:
so it is false, i.e. sizeof(X)<=16.
3) repeat with some other sensible values. e.g. try to guess that it is 16 i.e. sizeof(X)==16
. If it doesn't complain about duplicate case value. Then the expression is true.
4) optionally add a case 16
to verify it e.g.
#include <stdio.h>
typedef struct _X {
int a;
char b[10];
} X;
int main()
{
printf("Hello World");
int dummy=0 ;
switch (dummy) {
// case 1==2:
case sizeof( X):
case 16:
break;
}
return 0;
}
result
main.c: In function ‘main’:
main.c:15:5: error: duplicate case value
case 16:
^~~~
main.c:14:5: error: previously used here
case sizeof( X):
confirming that sizeof(X) is 16.
Alternatively, it is observed that gcc can report multiple duplicates, so this trick is possible for making multiple guesses on a single pass:
#include <stdio.h>
typedef struct _X {
int a;
char b[10];
} X;
int main()
{
printf("Hello World");
int dummy=0 ;
switch (dummy) {
case 1==2: //represents false
case 1==1: //represents true
case sizeof( X)>10:
case sizeof( X)>12:
case sizeof( X)>14:
case sizeof( X)>16:
case sizeof( X)==16:
//case 16:
break;
}
return 0;
}
result
main.c: In function ‘main’:
main.c:14:5: error: duplicate case value
case sizeof( X)>10:
^~~~
main.c:13:5: error: previously used here
case 1==1:
^~~~
main.c:15:5: error: duplicate case value
case sizeof( X)>12:
^~~~
main.c:13:5: error: previously used here
case 1==1:
^~~~
main.c:16:5: error: duplicate case value
case sizeof( X)>14:
^~~~
main.c:13:5: error: previously used here
case 1==1:
^~~~
main.c:17:5: error: duplicate case value
case sizeof( X)>16:
^~~~
main.c:12:5: error: previously used here
case 1==2:
^~~~
main.c:18:5: error: duplicate case value
case sizeof( X)==16:
^~~~
main.c:13:5: error: previously used here
case 1==1:
^~~~
suggesting the sizeof(X)
is >10, >12, >14 but is not >16. The ==16 is added as a final guess.
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.
Quick and simple solution that worked for me (GCC):
(char[sizeof(long long)])"bla";
This results in an error message that reveals the size of long long
:
ISO C++ forbids casting to an array type 'char [8]'
The following way, which works in GCC, Clang, MSVC and more, even in older versions, is based on failed conversion of a function parameter from pointer to array to a scalar type. The compilers do print size of the array, so you can get the value from the output. Works both in C and C++ mode.
Example code to find out sizeof(long)
(play with it online):
char checker(int);
char checkSizeOfInt[sizeof(long)]={checker(&checkSizeOfInt)};
Examples of relevant output:
<source>:1: note: expected 'int' but argument is of type 'char (*)[8]'
<source>:1:6: note: candidate function not viable: no known conversion from 'char (*)[8]' to 'int' for 1st argument;
<source>(2): warning C4047: 'function': 'int' differs in levels of indirection from 'char (*)[4]'
//main.cpp
#include <cstddef>
template <std::size_t x>
struct show_size;
void foo()
{
show_size<sizeof(my_type)>();//!!please change `my_type` to your expected
}
int main()
{
return 0;
}
You can compile this pretty simple code, and during its pre-compilation stage, the compiler will give error, in which the sizeof(my_type)
will give concrete value. e.g.:
g++ main.cpp