Comment obtenir le type d'une variable dans le code C?
Est-il possible que je peux découvrir le type d'une variable automatiquement en C, soit par le biais d'un mécanisme au sein du programme lui-même, ou-plus probablement-par le biais d'une pré-compilation script qui utilise le compilateur passe à l'endroit où il a analysé les variables et leurs types? Je suis à la recherche de suggestions d'ordre général à ce sujet. Ci-dessous plus d'information sur ce dont j'ai besoin et pourquoi.
Je voudrais changer la sémantique de la OpenMP clause de réduction. À ce stade, il semble plus facile simplement de remplacer la clause dans le code source (via un script) avec un appel à une fonction, et puis je peux définir la fonction de mettre en œuvre la réduction de la sémantique que je veux. Par exemple, mon script serait de convertir cette
#pragma omp parallel for reduction(+:x)
dans cette:
my_reduction(PLUS, &x, sizeof(x));
#pragma omp parallel for
où, précédemment, j'ai (dire)
enum reduction_op {PLUS, MINUS, TIMES, AND,
OR, BIT_AND, BIT_OR, BIT_XOR, /* ... */};
Et my_reduction
a la signature
void my_reduction(enum reduction_op op, void * var, size_t size);
Entre autres choses, my_reduction
aurait à appliquer l'opération d'addition à la réduction de la variable que le programmeur avait initialement prévu. Mais ma fonction ne peut pas savoir comment le faire correctement. En particulier, bien qu'il connaît la nature de l'opération (PLUS
), l'emplacement de la variable d'origine (var
), et la taille du type de la variable, il ne sait pas le type de la variable elle-même. En particulier, il ne sait pas si var
a un entier ou à virgule flottante de type. À partir d'un faible niveau de POV, l'opération d'addition de ces deux classes de types complètement différents.
Si seulement la non standard de l'opérateur typeof
, le GCC prend en charge, fonctionne de la manière sizeof fonctionne--retour d'une sorte de type de variable, je pourrais résoudre ce problème facilement. Mais typeof n'est pas vraiment comme sizeof: il ne peut être utilisé, apparemment, dans l'-les déclarations de valeur.
Maintenant, le compilateur ne peut évidemment connaître le type de x avant la fin de la génération du code exécutable. Ce qui m'amène à me demander si je peux en quelque sorte l'effet de levier du CCG analyseur, juste pour obtenir x
's type et le transmettre à mon script et exécutez GCC encore une fois, tout le chemin, pour compiler mes modifié le code source. Il serait alors assez simple de déclarer
enum var_type { INT8, UINT8, INT16, UINT16, /* ,..., */ FLOAT, DOUBLE};
void my_reduction(enum reduction_op op, void * var, enum var_type vtype);
Et my_reduction
peut jeter de façon appropriée avant de déférence et de l'application de l'opérateur.
Comme vous pouvez le voir, je suis en train de créer une sorte de "dispatching" mécanisme de C. Pourquoi ne pas simplement utiliser le C++ surcharge? Parce que mon projet me contraint à travailler avec l'héritage de code source écrit en C. je peux modifier le code automatiquement avec un script, mais je ne peux pas réécrire dans une autre langue.
Merci!
Merci, Alex. Qui semble aller dans la bonne direction.
J'ai lu quelque part que définis par l'utilisateur de réduction sera de la partie de l'3.1 ou 4.0 standard. Hm 3.1 dit:
reduction({operator|intrinsic_procedure_name}:list)
..jamais essayé intrinsic_procedure_name. cependant il ne résout en partie le type de détection.nvm.
intrinsic_procedure_name
se réfère à quelque chose d'autre.OriginalL'auteur Amittai Aviram | 2012-02-06
Vous devez vous connecter pour publier un commentaire.
C11
_Generic
Pas une solution directe, mais il ne vous permet pas d'obtenir le résultat souhaité si vous êtes patient, de code de tous les types:
Compiler et exécuter avec:
Un bon point de départ avec des tonnes de types peuvent être trouvés dans cette réponse.
Testé sur Ubuntu, 17.10, GCC 7.2.0. GCC seulement ajouté la prise en charge de 4,9.
OriginalL'auteur Ciro Santilli 新疆改造中心 六四事件 法轮功
C n'ont pas vraiment de façon de l'effectuer au préalable moment de la compilation, sauf si vous écrivez un flot de macros. Je pas recommander l'inondation de macros approche, essentiellement, il devait aller comme ceci:
Noter que c'est une très mauvaise pratique et ne devraient être utilisés qu'en dernier recours lors de l'entretien de mal écrits du code legacy, si même alors. Il n'y a pas de type de sécurité ou d'autres de telles garanties avec cette approche.
Une approche plus sûre est d'appeler explicitement
int_reduction()
de l'appelant, ou à l'appel d'une fonction générique qui décide du type d'exécution:Si int_reduction est incorporé et divers autres optimisations sont faites, ce moteur d'exécution de l'évaluation qui n'est pas forcément beaucoup plus lent que l'obfuscation des macros, mais il est beaucoup plus sûr.
Comment savez-vous quand vous déclarez une variable comme
int
? Je n'ai aucune idée de la nature de vos données ou d'où il vient, donc je ne peux pas répondre à cette question. Si il est une sorte de externe de données brutes, alors vous aurez naturellement, de déterminer le type de données avant d'effectuer tout calcul. Et c'est un algorithme question qui n'a rien à voir avec la programmation en C de la syntaxe en tant que tel.pas de. L'image est plus comme ça. Supposons que vous avez un
main
fonction de la déclarationint x
près du sommet. Dire 100 lignes en bas, vous avez#pragma omp parallel for reduction (+:x)
. Lex
il y a le typeint
parce que c'est la façon dont il a été déclaré dans le champ d'application actuel. Le programmeur sait et peut annoter un appel de fonction de lui-même, mais je veux être capable de faire cela automatiquement.Le code source existe déjà, avec les déclarations de variables et OpenMP pragmas. Ce que je veux faire est automatiquement refactoriser le code pour remplacer le
reduction
clause avec un appel de fonction de la formereduction(enum reduction_op, void * var, enum type, size_t size)
(ou quelque chose de similaire). Mon problème est que la forme de lareduction
clause n'a pas, lui-même, toute représentation du type de la variable, depuis--bien sûr--le compilateur est présumé connaître le type quand il arrive à cette clause.Soit vous devez déclarer le type de données d'origine comme un struct, avec le type enum comme premier membre, puis de passer un pointeur vers cette structure à une fonction. Ou garder la variable d'origine, mais inclure le type de l'appel à la fonction/macro. Il n'y a pas d'autres alternatives dans la norme C.
OriginalL'auteur Lundin
Vous pouvez utiliser sizeof fonction pour déterminer le type , laissez la variable de type inconnu-être var.
puis
Tu elle conduit à des complications lors de deux ou plus de deux principaux types peuvent avoir la même taille .
OriginalL'auteur joker007
Vous pourriez aussi considérer la personnalisation de GCC avec un plugin ou un Faire FONDRE extension pour répondre à vos besoins. Cependant, cela nécessite la compréhension de certains de GCC représentations internes (Gimple, Arbre) qui sont complexes (donc de vous prendre des jours de travail au moins).
Mais les types sont une compilation seule chose en C. Ils ne sont pas réifiée.
OriginalL'auteur Basile Starynkevitch
GCC fournit la typeof extension. Il n'est pas standard, mais assez commun (plusieurs autres compilateurs, par exemple, clang/llvm, en avoir un).
Vous pourriez peut-être envisager de personnalisation de la GCC en l'étendant avec Faire FONDRE (un langage spécifique au domaine d'étendre GCC) pour s'adapter à vos besoins.
Il n'est pas standard et ne fonctionne pas sur la plupart des compilateurs C. Dans mon expérience, c'est une très mauvaise idée d'utiliser des extensions de GCC pour la production de code.
OriginalL'auteur Basile Starynkevitch