Подтвердить что ты не робот

Определить `sizeof float` без компиляции

Я хотел бы знать размер float в GCC, без необходимости запуска компилятора. Я знаю, что один из вариантов заключается в том, чтобы написать небольшую функцию и распечатать распечатку компилятора.

Существует limits.h, который содержит минимумы и максимумы, но есть ли что-то подобное, которое сообщает размер разных неявных типов?

Я использую GCC для Windows 7 x64; целевой платформой является 32-битный режим ARM7. Язык - C.

4b9b3361

Ответ 1

Вы можете иметь 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

Ответ 2

Ответ 4. Любая разумная реализация C соответствует IEEE 754, которая определяет float ( "single precision" ) как 32-битный двоичный тип с плавающей запятой с 1 знаковым битом, 23 мантиссами и 8 экспоненциальными битами, Вы никогда не столкнетесь с чем-либо другим в этом мире.

Этот ответ еще более определен, так как вы указали GCC. GCC не поддерживает какие-либо цели, где float не является 32-разрядным.

Ответ 3

Предполагая, что вы просто хотите, чтобы это помогло вам определить, какой размер различных типов в вашей целевой системе не нужен, чтобы фактически запустить программу в целевой системе, но вы не планируете использовать ее как инструмент в систему сборки, у меня может быть хак для вас...

В hack требуется запуск компилятора для компиляции программы, но вам не нужно запускать скомпилированный вывод в любом месте. Фактически, этот хак предназначен для того, чтобы рассказать вам, что вы хотите знать, генерируя ошибки компилятора.

Маленький макрос здесь заставит компилятор выплюнуть сообщение об ошибке, соответствующее размеру указанного типа. Он также выплюнет сообщение об ошибке "конец поиска", если вы передадите ему тип, который больше, чем он проверяет. Это просто "удобство", чтобы напомнить вам пойти добавить в макрос больше строк, чтобы он обрабатывал тип, который вам интересен.

Некоторые из основных ограничений:

  • это ужасно хакерский
  • он сообщает вам информацию ужасно ужасным способом.
  • он будет работать только с типами, которые могут быть выражены как одно слово (так что 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 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 из-за различий в выравнивании/дополнении)

Надеюсь, это поможет. На самом деле, были времена, когда я хотел бы этого... Как правило, если мне интересно узнать размер структуры на моих встроенных объектах, то я обманываю в отладчике эту информацию или мне нужно взломать отладочную версию printf() где-то.

Я думаю, что это было бы проще в использовании:

  • интересно, как сильно что-то есть
  • отбросить SAY_SIZEOF() 'вызов' в исходный файл
  • нажмите Shift-Ctrl-B (или что бы горячая клавиша не компилировала/не создавала), получите информацию и
  • удалить SAY_SIZEOF() 'call'

Ответ 4

Другой вариант может быть gdb: просто запустите его без какой-либо программы и выполните sizeof(float). Проблема в том, что ваша целевая и хост-платформа не одинаковы, поэтому вам придется запускать их на вашем gdb-устройстве.