Определить 'sizeof float' без компиляции
Я хотел бы знать размер float
в GCC, без необходимости запускать компилятор. Я знаю, что один из вариантов-написать небольшую функцию и заставить компилятор распечатать список сборок.
здесь limits.h
, который содержит минимумы и максимумы, но есть ли что-то подобное, что говорит о размере различных неявных типов?
Я использую GCC в Windows 7 x64; целевая платформа-32-битный режим ARM7. Язык С.
4 ответов
вы можете распечатать GCC все макросы по умолчанию:
gcc -dM -E - </dev/null | grep FLT
затем вы получаете строки, такие как:
#define __FLT_MANT_DIG__ 24
#define __FLT_MAX_EXP__ 128
теперь вы можете обработать следующим образом:
24 + lg(128) + 1 = 32
найти документацию:
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) фактические макросы:
http://www.gnu.org/s/hello/manual/libc/Floating-Point-Parameters.html
ответ 4. Любая разумная реализация C соответствует IEEE 754, который определяет float
("одиночная точность") как 32-разрядный двоичный тип с плавающей запятой с 1 битом знака, 23 битами мантиссы и 8 битами экспоненты. Вы никогда не столкнетесь с чем-то отличным от этого в реальном мире.
этот ответ еще более окончательный, так как вы указали GCC. GCC не поддерживает никаких целей, где float
не является 32-битным.
предполагая, что вы просто хотите, чтобы это помогло вам определить, какой размер различных типов в вашей целевой системе без необходимости фактически запускать программу в целевой системе, но вы не собираетесь, чтобы это был какой-то инструмент, интегрированный в систему сборки, у меня может быть хак для вас...
взлом требует запуска компилятора для компиляции программы, но вам не нужно запускать скомпилированный вывод в любом месте. На самом деле, этот хак предназначен, чтобы сказать вам, что вы хотите знать, генерируя ошибки компилятора.
маленький макрос здесь заставит компилятор выплюнуть сообщение об ошибке, соответствующее размеру данного типа. Он также выплюнет сообщение об ошибке "конец поиска" на случай, если вы передадите ему тип, который больше, чем он проверяет. Это просто "удобство", чтобы напомнить вам, чтобы добавить кучу больше строк в макрос, чтобы он обрабатывал тип, который вам интересен.
некоторые из основных ограничений являются:
- это ужасно суховато
- он сообщает вам информацию в бог-ужасный способ
- это будет работать только с типами, которые могут быть выражены одним словом (так
typedef
необходимо для таких вещей, какlong double
как показано в Примере).
но если вам когда-нибудь интересно размер какого-либо типа, и не хотите на самом деле запускать программу на целевой printf()
информация, это может помочь.
здесь макрос(ы) вместе с некоторыми примерами его использования:
#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;
}
и вот что говорит компиляция этой программы с GCC / MinGW 4.5.1:
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
таким образом, вы можете легко увидеть, что:
-
float
4 байта -
long double
- это 12 байт -
struct foo
8 байт -
struct bar
составляет 12 байт (отличается отstruct foo
из-за различий выравнивания / заполнения)
надеюсь, что это помогает. На самом деле, там были времена, когда я хотел этого... Как правило, если мне интересно размер структуры на моих встроенных целях, я ковыряюсь в отладчике для этой информации или мне нужно взломать debug printf()
куда-то.
Я думаю, что это было бы легче использовать:
- интересно, насколько что-то большое
- падение
SAY_SIZEOF()
'call' в исходный файл - нажмите Shift-Ctrl-B (или любую горячую клавишу для компиляции / сборки), получите информацию, и
- удалить
SAY_SIZEOF()
'call'
другим вариантом может быть gdb: просто запустите его без какой-либо программы и выполните sizeof(float)
. Проблема в том, что ваша целевая и хост-платформа не одинаковы, поэтому вам придется запускать их на вашем arm-gdb.