web-dev-qa-db-fra.com

Comment puis-je imprimer le résultat de sizeof () lors de la compilation en C?

Comment puis-je imprimer le résultat de sizeof () lors de la compilation en C?

Pour le moment, j'utilise une assertion statique (créée à la maison à partir d'autres ressources Web) pour comparer le résultat de sizeof () à différentes constantes. Bien que cela fonctionne ... il est loin d'être élégant ou rapide. Je peux aussi créer une instance de la variable/struct et regarder dans le fichier map mais c'est aussi moins élégant et rapide qu'un appel direct/commande/opérateur. En outre, il s’agit d’un projet intégré qui utilise plusieurs compilateurs croisés ... Il est donc plus compliqué de générer et de charger un exemple de programme dans la cible, puis de lire une valeur.

Dans mon cas (ancien GCC), #warning sizeof(MyStruct) n'interprète pas réellement sizeof () avant d'imprimer l'avertissement.

33
altendky

Je cherchais des fonctionnalités similaires lorsque je suis tombé sur ceci:

Est-il possible d'imprimer la taille d'une classe C++ au moment de la compilation?

Ce qui m'a donné l'idée de cela:

char (*__kaboom)[sizeof( YourTypeHere )] = 1;

Ce qui entraîne l'avertissement suivant dans VS2015:

warning C4047: 'initializing': 'DWORD (*)[88]' differs in levels of indirection from 'int'

où 88 dans ce cas serait la taille que vous cherchez.

Super hacky, mais ça fait l'affaire. Probablement quelques années trop tard, mais j'espère que cela sera utile à quelqu'un. 

Je n'ai pas encore eu l'occasion d'essayer avec gcc ou clang, mais je vais essayer de confirmer si cela fonctionne ou non si quelqu'un ne le fait pas avant moi.

Edit: Fonctionne immédiatement pour Clang 3.6

Le seul truc que je pouvais travailler pour GCC était d’abuser de -Wformat et de laisser la macro définir une fonction comme celle-ci:

void kaboom_print( void )
{
    printf( "%d", __kaboom );
}

Ce qui va vous donner un avertissement comme:

...blah blah blah... argument 2 has type 'char (*)[88]'

Un peu plus grossier que la suggestion initiale, mais peut-être que quelqu'un qui connaît un peu mieux gcc peut penser à un meilleur avertissement contre les abus.

39
Bakhazard

Tout ce dont vous avez besoin, c'est d'une astuce qui oblige le compilateur à se plaindre de l'utilisation incorrecte de certaines valeurs entières lors de la compilation, comme dupliqué case constant:

struct X {
    int a,b;
    int c[10];
};
int _tmain(int argc, _TCHAR* argv[])
{
    int dummy;

    switch (dummy) {
    case sizeof(X):
    case sizeof(X):
        break;
    }
    return 0;
}

------ Construction démarrée: Projet: cpptest, Configuration: Debug Win32 ------ cpptest.cpp c:\travail\cpptest\cpptest\cpptest.cpp (29): erreur C2196: valeur de cas '48' déjà utilisé ========== Build: 0 a réussi, 1 a échoué, 0 à jour, 0 ignoré ==========

Donc, la taille de la struct X est 48

6
JavaMan

Une autre façon (qui fonctionne réellement):

char __foo[sizeof(MyStruct) + 1] = {[sizeof(MyStruct)] = ""};

Fonctionne avec old'ish gcc 5.x. Donne une erreur comme celle-ci:

a.c:8:54: error: initializer element is not computable at load time
a.c:8:54: note: (near initialization for 'a[8]')

p.s. évidemment, celui-ci est (très) spécifique à gcc. Toutes les autres méthodes ne fonctionnaient pas pour moi.

2
Konstantin Stupnik

Mon compilateur gcc C refuse d’imprimer la taille en utilisant l’une des solutions ci-dessus. J'ai inversé la logique pour injecter des avertissements du compilateur pour quelle taille ce n'est pas.

enum e
{
    X = sizeof(struct mystruct)
};

void foo()
{
    static enum e ev;

    switch (ev)
    {
    case 0:
    case 4:
    case 8:
    case 12:
    case 16:
    case 20:
        break;
    }
}

Ensuite, je dois regarder à travers les avertissements pour le nombre manquant.

warning: case value '0' not in enumerated type 'e' [-Wswitch]
warning: case value '4' not in enumerated type 'e' [-Wswitch]
warning: case value '12' not in enumerated type 'e' [-Wswitch]
warning: case value '16' not in enumerated type 'e' [-Wswitch]
warning: case value '20' not in enumerated type 'e' [-Wswitch]

Alors ma taille de structure est 8.

Mon emballage est 4.

Meh ... c'est une option.

0
jws

Je suis tombé sur une solution similaire à Bakhazard 's excellente solution , et celle-ci produit un avertissement beaucoup moins verbeux.

char (*__fail)(void)[sizeof(uint64_t)] = 1;

Cela produit le message d'erreur

Function cannot return array type 'char [8]'

Cela a été testé avec la dernière version de clang(1).

0
EHYPERCHICKEN

Bien que ce ne soit pas exactement au moment de la compilation, c'est est avant l'exécution, donc cela pourrait toujours être pertinent pour certaines personnes.

Vous pouvez définir un tableau comme ceci:

uint8_t __some_distinct_name[sizeof(YourTypeHere)];

Et ensuite, après la compilation, récupérez la taille du fichier objet:

$ nm -td -S your_object_file |       # list symbols and their sizes, in decimal
  grep ' __some_distinct_name$' |    # select the right one
  cut -d' ' -f2 |                    # grab the size field
  xargs printf "Your type is %d B\n" # print
0
user10746164