Déterminer `sizeof float` sans compilation

J’aimerais connaître la taille d’un float dans GCC, sans avoir à exécuter le compilateur. Je sais qu’une option consiste à écrire une petite fonction et à demander au compilateur d’imprimer une liste d’assemblages.

Il y a limits.h , qui contient les minimums et les maximums, mais y a-t-il quelque chose de similaire qui indique la taille des différents types implicites?

J’utilise GCC sur Windows 7 x64; la plate-forme cible est le mode ARM7 32 bits. La langue est C.

Vous pouvez avoir GCC imprimer toutes les macros par défaut:

 gcc -dM -E -  

Ensuite, vous obtenez des lignes comme:

 #define __FLT_MANT_DIG__ 24 #define __FLT_MAX_EXP__ 128 

Maintenant, vous pouvez parsingr ceci comme suit:

 24 + lg(128) + 1 = 32 

Pour trouver de la documentation:

1) man gcc :

  -E Stop after the preprocessing stage; do not run the comstackr 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 comstackr 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) les macros réelles:

http://www.gnu.org/s/hello/manual/libc/Floating-Point-Parameters.html

La réponse est 4. Toute implémentation C raisonnable répond à la norme IEEE 754, qui définit float (“simple précision”) comme un type à virgule flottante binary 32 bits avec 1 bit de signe, 23 bits de mantisse et 8 bits d’exposant. Vous ne rencontrerez jamais rien de différent de cela dans le monde réel.

Cette réponse est encore plus définitive depuis que vous avez spécifié GCC. GCC ne prend en charge aucune cible où float n’est pas 32 bits.

En supposant que vous souhaitiez simplement que cela vous aide à déterminer la taille des différents types sur votre système cible sans avoir à exécuter un programme sur le système cible, mais vous n’avez pas l’intention de faire de cet outil un outil intégré à une construction. système, je peux avoir un bidouillage pour vous …

Le hack nécessite l’exécution du compilateur pour comstackr un programme, mais vous n’avez pas à exécuter la sortie compilée où que vous soyez. En fait, ce hack est conçu pour vous dire ce que vous voulez savoir en générant des erreurs de compilation.

La petite macro ici entraînera le compilateur à cracher un message d’erreur correspondant à la taille du type donné. Il va également cracher un message d’erreur sur la “fin de la recherche” juste au cas où vous lui passeriez un type plus grand que ce qu’il vérifie. C’est simplement une “commodité” pour vous rappeler d’append plusieurs lignes à la macro afin qu’elle puisse traiter le type qui vous intéresse.

Certaines des principales limitations sont:

  • c’est horriblement hacky
  • il vous dit les informations d’une manière affreuse
  • cela ne marchera qu’avec des types qui peuvent être exprimés sous la forme d’un mot simple (une typedef est donc nécessaire pour des choses comme long double comme indiqué dans l’exemple).

Mais si vous êtes curieux de connaître la taille d’un type et que vous ne voulez pas exécuter un programme sur la cible pour printf() les informations, cela peut aider.

Voici la macro (s) avec quelques exemples d’utilisation:

 #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; } 

Et voici ce que dit ce programme avec 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 

Donc, vous pouvez facilement voir que:

  • float est 4 octets
  • long double est de 12 octets
  • struct foo est 8 octets
  • struct bar est de 12 octets (différente de struct foo raison des différences d’alignement / remplissage)

J’espère que cela t’aides. En fait, il y a eu des moments où je voulais cela … Généralement, si je suis curieux de la taille d’une structure sur mes cibles intégrées, je fouille dans le débogueur pour obtenir ces informations ou je dois pirater un printf() débogage printf() quelque part.

Je pense que ce serait effectivement plus facile à utiliser:

  • je me demande comment quelque chose est grand
  • déposer un ‘appel’ SAY_SIZEOF() dans le fichier source
  • appuyez sur Shift-Ctrl-B (ou quel que soit le raccourci clavier à comstackr / construire), obtenez les informations et
  • supprimer le SAY_SIZEOF() ‘appel’

Une autre option pourrait être gdb: lancez-le sans aucun programme et exécutez sizeof(float) . Le problème est que votre plate-forme cible et votre plate-forme hôte ne sont pas identiques, vous devez donc les exécuter sur votre arm-gdb.