Определить '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.