11
votes

Puis-je ré-définir une fonction ou vérifier s'il existe?

J'ai une question sur (re) définir des fonctions. Mon objectif est d'avoir un script où je peux choisir de définir une fonction ou non. Comme ceci: xxx

et sans la fonction, juste: xxx

personne une idée?


6 commentaires

Votre syntaxe n'a pas de sens. Essayez-vous de lancer?


Le préprocesseur est-il une option? Ensuite, vous pouvez définir une fonction selon laquelle une fonction différente est définie ou non, mais elle ne décidera que de la compilation


Vous ne pouvez pas utiliser de déclarations précompiler ou souhaitez-vous définir des méthodes de manière dynamique? Je ne suis pas sûr de pouvoir le faire.


@monkey, c'est une configuration rapide sans coulées


@Tim uniquement avec des pointeurs de fonction.


@TIM: Nous avons besoin de clarification ici. Votre terminologie est légèrement éteinte, alors peut-être que ce serait mieux si vous pouviez décrire vos objectifs plus larges?


8 Réponses :


5
votes

quelque chose comme ça, je pense. N'a pas beaucoup utilisé les pointeurs de fonction, alors j'ai peut-être pu avoir la syntaxe légèrement fausse.

  void func()
  {
#define FUNC_PRESENT
      // code
  }

  void (*funcptr)();

#ifdef FUNC_PRESENT
      funcptr = func;
#else
      funcptr = NULL;
#endif

  int main()
  {
      if (funcptr)
          funcptr();
  }


5 commentaires

N'est toujours pas dynamique comme il veut. Il devra vérifier contre une condition d'exécution et définir le pointeur de la fonction manuellement.


Je ne pense pas que #define fait ce que vous pensez. Les lignes commençant par # sont scannées et retirées du fichier source en séquence avant le début de la compilation, de sorte que func_present sera toujours définie lorsque vous arrivez au #Ifdef . Et mettre #define func_present dans une définition de la fonction n'a aucune signification utile.


+1: Bien que je ferais attention à écrire le #define lexiquement "à l'intérieur" de la définition de la fonction. Je reçois que vous essayez de regrouper le code ensemble, il est donc moins exposé aux erreurs de se déplacer, mais cela pourrait induire des codeurs induire en erreur dans le traitement de la définition de PP comme une chose qui ne se produit que lorsque Func () est appelé . [edit: ou il peut induire en erreur les programmeurs à penser que vous pensez que, comme Brian ci-dessus]


Ah, et le droit de Xaade; Vous pouvez faire cette dynamique avec une liaison créative, mais votre astuce de préprocesseur s'en va. Néanmoins, alors que ce n'est pas un produit prêt à l'emploi que l'OP peut employer, je pense que votre approche est la bonne.


@Brian: Tomalak comprit ce que je voulais dire. Je mettais le #define à l'intérieur de la définition de la fonction de sorte que si / lorsque la définition de fonction est supprimée du fichier / fichier d'en-tête, le code #include s, le # Définir va automatiquement avec elle.



3
votes

Vraiment le seul moyen que vous puissiez "choisir de définir une fonction ou non" est avec des directives de préprocesseur C. Par exemple: xxx

pour définir ces "variables" que vous utilisez #define quelque nom

Le problème est, tout cela doit être fait Au moment de la compilation (avant cela, effectivement), il ne peut donc pas être fait avec un si comme dans votre exemple. Si vous souhaitez qu'une instruction Si vous souhaitez contrôler votre flux de programme, utilisez-la et ne vous inquiétez pas d'essayer de renommer des fonctions ou d'utiliser des pointeurs de fonction ou quelque chose.


2 commentaires

C'est probablement la réponse la plus appropriée - C n'est pas si bon pour faire des choses très dynamiques.


+1 lié: Stackoverflow.com/Questions/6234755/...



4
votes

Utiliser les pointeurs de fonction, définissez-les de manière dynamique sur la base de conditions d'exécution et recherchez des pointeurs NULL ou de les envelopper dans des méthodes qui vous permettent de vérifier.

seule option en C, je peux penser.

en C ++, vous pouvez combiner des modèles et des dlls pour définir dynamiquement au moment de l'exécution.


0 commentaires

0
votes

en C? Seulement en utilisant le préprocesseur comme indiqué dans d'autres réponses.

C n'est pas une langue dynamique comme, disons, python.


0 commentaires

19
votes

Vous pouvez le faire dans GCC en utilisant son extension d'attribut de fonction faible: xxx

ceci fonctionne même si func () est défini dans un autre fichier .C ou un autre fichier. Bibliothèque.


12 commentaires

C'est assez cool. yay pour GCC. Les autres compilateurs soutiennent-ils des caractéristiques similaires, ou est-ce une chose à peu près une chose de GCC?


Oh, on dirait que d'autres compilateurs la supportent également avec l'utilisation de #pragma faible . en.wikipedia.org/wiki/weak_symbol


Hah! Techniquement pas une réponse [c] dans l'intégralité, mais est exactement ce que l'OP recherche et ce que ma réponse fonctionne autour d'un manque de choses.


@R.: Pourquoi GCC pourrait-il optimiser cela s'il s'agit d'une fonctionnalité de GCC spécifique?


Les symboles et les définitions faibles ont beaucoup d'utilisations, ce n'est qu'un d'entre eux. Cela peut fonctionner, mais je le regarderais et vérifierais. Il semble que je me souvienne d'un problème comme celui-ci, dans lequel l'optimiseur de GCC optimiserait des vérifications non nulles sur les adresses de fonction ou les comparaisons d'égalité entre les adresses de différentes fonctions (toutes deux des optimisations non valides avec des symboles faibles).


@R, j'utilise de cette manière dans un code de mien; Il semble de toute façon fonctionner sur Linux. GCC ne peut pas optimiser le si (FUNC) sauf s'il existe une définition dans la même unité de compilation, car elle ne sait pas si une définition sera fournie par une autre unité de compilation ou partagée Bibliothèque, etc.


Wow, cloué la question. Bien que je pense que dans 5 ans, quelqu'un va rencontrer son code en utilisant cette extension et WTF.


@Brian: C'est ce que font les commentaires et la documentation.


@Jab personnellement, je suis habituellement utilisé pour voir la documentation expliquant quel code fait, ne pas expliquer pourquoi le code que je regarde n'est pas C


@Brian: Il existe une différence entre "étant une extension de compilateur non portable / compilateur à la norme C" et "ne pas être c".


@Jab: Franchement, c'est une belle ligne fine.


Comment cela marche-t-il? Il échoue toujours à l'étape de liaison de toute façon à l'aide de GCC sur mes macos



0
votes

La bonne façon de faire ce que je pense que vous demandez que vous demandez dans C est d'utiliser pointeurs de fonction . Vous pouvez prendre l'adresse d'une fonction, l'attribuer à une variable, le tester pour nul, etc. Cependant, l'ancien CLI C n'est pas une langue très dynamique; Vous êtes peut-être préférable d'utiliser une langue différente.


0 commentaires

1
votes

Introduction

Je suppose que vous essayez de faire ceci: p>

  • deux modules, a.o code> et b.o code> li>
  • b.o code> contient une définition pour void foo () code> li>
  • AO code> Appels void foo () code> seul em> si bo code> est également lié à l'exécutable final. li> ul>

    Ceci pourrait être utile pour un système "plug-in". P>


    Variation 1 H1>

    Vous pouvez le simuler à l'aide des pointeurs de fonction. Je ne sais pas assez C pour écrire ceci dans le code C approprié, mais la pseudocode ressemble à ceci: P>

    AH H2>
    #include "a.h"
    fptr_t ayb_ptr = 0;
    


7 commentaires

Juste une note, mais en C, un pointeur à une fonction serait attribué dans un format tel que retour_type (* arguments) = nom_of_function_being_pointed_to_without_trailing_Parent ES; ; Les pointeurs de fonction sont généralement nécessaires pour avoir le même prototype que les fonctions qu'ils indiquent, mais si vous avez un TypeDef pour le pointeur de fonction ( Typedef retour_type (* Typef_Name) (args); ), vous pouvez lancer La fonction étant signalée vers la TYPEDEF et évite ainsi une erreur de compilateur (mais invite la possibilité de causer des SEGFAULTS ou similaires au moment de l'exécution en raison d'un nombre incorrect d'arguments et de tels).


@JAB: Juste une note, mais ce n'est pas une mission. :)


Mon utilisation de la terminologie de côté, des choses comme static int dummy = addfuncptr (& bar); et fptr_t bar_ptr = & bar; serait statique int DMOY = addfuncptr (bar ); et fptr_t bar_ptr = barre; en C, en raison de la manière dont les fonctions sont traitées.


@Jab: Okie Doke. Bravo :) En C ++, les deux sont à peu près la même chose.


@JAB: ERM, pour être juste, Cela semble être le cas en C trop .


Je vois. Ne pense pas que j'ai jamais vu que cela soit réellement utilisé dans le format & lol , probablement, probablement parce que dans les cas où vous ne savez pas si c'est le nom de la fonction réelle ou si c'est juste un pointeur Fonction Vous pourriez segfault si vous n'êtes pas prudent . (Cela serait probablement un problème dans des situations dans lesquelles une fonction prend une autre fonction comme l'un de ses arguments et que vous pourriez ainsi passer un nom de fonction ou un pointeur à une fonction.)


@Jab: Honnêtement, je ne pense pas qu'il y a une distinction. Le seul moyen de passer un "nom de la fonction" d'une manière autre que comme un pointeur de fonction serait lexiquement, à l'intérieur d'une chaîne. [EDIT: Oh, je vois ce que tu veux dire. Eh bien, prendre l'adresse d'une fonction le pointeur est quelque chose de très différent. Je concède qu'il peut y avoir un élément de la nessoire d'erreur ici. Néanmoins, il n'y a pas de "passage d'un nom de fonction"; Vous parlez de passer un pointeur de fonction vs transmettre un pointeur à un pointeur de fonction.]



0
votes

Si vous n'éventez pas l'extension spécifique du compilateur, vous pouvez utiliser __ if_exists : xxx

ceci fonctionne par défaut par défaut et en clang si vous utilisez le -FMS-Extensions Drapeau.


0 commentaires