I'd like to know the size of a float
in GCC, without having to run the compiler. I know one option is to write a small function and have the compiler print out an assembly listing.
There is limits.h
, which contains the minimums and maximums, but is there something similar that tells the size of the different implicit types?
I'm using GCC on Windows 7 x6开发者_C百科4; the target platform is ARM7 32 bit mode. Language is C.
You can have GCC print out all of the default macros:
gcc -dM -E - </dev/null | grep FLT
Then you get lines like:
#define __FLT_MANT_DIG__ 24
#define __FLT_MAX_EXP__ 128
Now you can parse this as follows:
24 + lg(128) + 1 = 32
To find documentation:
1) man gcc
:
-E Stop after the preprocessing stage; do not run the compiler proper.
The output is in the form of preprocessed source code, which is
sent to the standard output.
...
-dCHARS
CHARS is a sequence of one or more of the following characters, and
must not be preceded by a space. Other characters are interpreted
by the compiler proper, or reserved for future versions of GCC, and
so are silently ignored. If you specify characters whose behavior
conflicts, the result is undefined.
M Instead of the normal output, generate a list of #define
directives for all the macros defined during the execution of
the preprocessor, including predefined macros. This gives you
a way of finding out what is predefined in your version of the
preprocessor. Assuming you have no file foo.h, the command
touch foo.h; cpp -dM foo.h
will show all the predefined macros.
2) the actual macros:
http://www.gnu.org/s/hello/manual/libc/Floating-Point-Parameters.html
The answer is 4. Any reasonable C implementation conforms to IEEE 754, which defines float
("single precision") as a 32-bit binary floating point type with 1 sign bit, 23 mantissa bits, and 8 exponent bits. You will never encounter anything different from this in the real world.
This answer is even more definitive since you specified GCC. GCC does not support any targets where float
is not 32-bit.
Assuming that you just want this to help you determine what the size of various types on your target system is without having to actually run a program on the target system, but you don't intend on this being some sort of tool integrated into a build system, I may have a hack for you...
The hack does require running the compiler to compile a program, but you don't have to run the compiled output anywhere. In fact, this hack is designed to tell you what you want to know by generating compiler errors.
The little macro here will cause the compiler to spit out an error message that corresponds to the size of the type given. It'll also spit out an error message about the 'end of the search' just in case you pass it a type that's larger than what it checks. That's just a 'convenience' to remind you to go add a bunch more lines to the macro so it'll handle the type you're curious about.
Some of the main limitations are:
- it's horribly hacky
- it tells you the information in a god-awful way
- it'll only work with types that can be expressed as a single word (so a
typedef
is necessary for things likelong double
as shown in the example).
But if you're ever curious about the size of some type, and don't want to actually run a program on the target to printf()
the information, this may help.
Here's the macro(s) along with some examples of it being used:
#if !defined( PASTE)
#define PASTE2( x, y) x##y
#define PASTE( x, y) PASTE2( x, y)
#endif /* PASTE */
#define SAY_IF_SIZEOF( type, size) static char PASTE( PASTE( PASTE( sizeof_, type), _is_), size) [(sizeof(type) == (size)) ? -1 : 1]
#define SAY_SIZEOF_END(type) static char PASTE( end_search_for_sizeof_, type)[-1]
#define SAY_SIZEOF(type) \
SAY_IF_SIZEOF( type, 1); \
SAY_IF_SIZEOF( type, 2); \
SAY_IF_SIZEOF( type, 3); \
SAY_IF_SIZEOF( type, 4); \
SAY_IF_SIZEOF( type, 5); \
SAY_IF_SIZEOF( type, 6); \
SAY_IF_SIZEOF( type, 7); \
SAY_IF_SIZEOF( type, 8); \
SAY_IF_SIZEOF( type, 9); \
SAY_IF_SIZEOF( type, 10); \
SAY_IF_SIZEOF( type, 11); \
SAY_IF_SIZEOF( type, 12); \
SAY_IF_SIZEOF( type, 13); \
SAY_IF_SIZEOF( type, 14); \
SAY_IF_SIZEOF( type, 15); \
SAY_IF_SIZEOF( type, 16); \
SAY_SIZEOF_END(type)
//here's where you get to ask about the size of a type
SAY_SIZEOF(float);
typedef long double long_double;
SAY_SIZEOF(long_double);
struct foo {
char x;
short y;
int* p;
};
struct bar {
char x;
int* p;
short y;
};
typedef struct foo foo_t;
typedef struct bar bar_t;
SAY_SIZEOF(foo_t);
SAY_SIZEOF(bar_t);
int main(void)
{
return 0;
}
And here's what compiling that program with GCC/MinGW 4.5.1 says:
C:\temp\test.c:34:1: error: size of array 'sizeof_float_is_4' is negative
C:\temp\test.c:34:1: error: size of array 'end_search_for_sizeof_float' is negative
C:\temp\test.c:38:1: error: size of array 'sizeof_long_double_is_12' is negative
C:\temp\test.c:38:1: error: size of array 'end_search_for_sizeof_long_double' is negative
C:\temp\test.c:56:1: error: size of array 'sizeof_foo_t_is_8' is negative
C:\temp\test.c:56:1: error: size of array 'end_search_for_sizeof_foo_t' is negative
C:\temp\test.c:57:1: error: size of array 'sizeof_bar_t_is_12' is negative
C:\temp\test.c:57:1: error: size of array 'end_search_for_sizeof_bar_t' is negative
So, you can easily see that:
float
is 4 byteslong double
is 12 bytesstruct foo
is 8 bytesstruct bar
is 12 bytes (different thanstruct foo
due to alignment/padding differences)
Hope this helps. Actually, there have been times when I would want this... Generally, if I'm curious about the size of a struct on my embedded targets I poke around in the debugger for that info or I have to hack in a debug printf()
somewhere.
I think this would actually be easier to use:
- wonder how big something is
- drop a
SAY_SIZEOF()
'call' into the source file - hit Shift-Ctrl-B (or whatever the hotkey is to compile/build), get the info, and
- delete the
SAY_SIZEOF()
'call'
Another option could be gdb: Just run it without any program and execute sizeof(float)
. The problem is that your target and host platform are not the same, so you would have to run them on your arm-gdb.
精彩评论