Les pointeurs peuvent être déclarés comme pointant vers des données mutables (non const) ou comme pointeur vers des données constantes.
Les pointeurs peuvent être définis pour pointer vers une fonction.
Mes collègues et moi avons discuté de l'utilisation de "const" avec des pointeurs et la question qui a été posée à propos de l'utilisation de const
avec des pointeurs de fonction a été soulevée.
Voici quelques questions:
typedef void (*Function_Pointer)(void); // Pointer to void function returning void.
void function_a(Function_Pointer p_func); // Example 1.
void function_b(const Function_Pointer p_func); // Example 2.
void function_c(Function_Pointer const p_func); // Example 3.
void function_d(const Function_Pointer const p_func); // Example 4.
Les déclarations ci-dessus sont des exemples de traitement d'un pointeur de fonction comme un pointeur sur un type intrinsèque.
Un pointeur de données, de variable ou de mémoire permet les combinaisons ci-dessus.
Les questions sont donc les suivantes: un pointeur de fonction peut-il avoir les mêmes combinaisons et que signifie un pointeur sur une fonction const (comme dans l'exemple 2)?
En C, il n’existe pas de fonction const
ou autre, donc un pointeur sur une fonction const n’a pas de sens (il ne faut pas compiler, même si je n’ai vérifié avec aucun compilateur en particulier).
Notez que bien que ce soit différent, vous pouvez avoir un pointeur const sur une fonction, un pointeur sur une fonction renvoyant const, etc. Essentiellement, tout sauf la fonction elle-même peut être const. Prenons quelques exemples:
// normal pointer to function
int (*func)(int);
// pointer to const function -- not allowed
int (const *func)(int);
// const pointer to function. Allowed, must be initialized.
int (*const func)(int) = some_func;
// Bonus: pointer to function returning pointer to const
void const *(*func)(int);
// triple bonus: const pointer to function returning pointer to const.
void const *(*const func)(int) = func.
Pour ce qui est de passer un pointeur sur une fonction en tant que paramètre, c'est assez simple. Vous voulez normalement simplement passer un pointeur sur le type correct. Toutefois, un pointeur sur n'importe quel type de fonction peut être converti en un pointeur sur un autre type de fonction, puis revenir à son type d'origine et conserver la valeur d'origine.
Selon la spécification C ( C99 , section 6.7.3):
Les propriétés associées aux types qualifiés ne sont significatives que pour les expressions Qui sont des lvalues.
Lorsque la spécification dit "types qualifiés", cela signifie des éléments définis avec le mot clé const
, restrict
ouvolatile
. Les fonctions Snice ne sont pas des valeurs, le mot clé const
d'une fonction n'a pas de sens. Vous envisagez peut-être une sorte d’extension spécifique au compilateur. Certains compilateurs émettront une erreur si vous essayez de déclarer une fonction en tant que const
.
Êtes-vous sûr de regarder un pointeur sur une fonction constante et non un pointeur constant sur une fonction (c'est-à-dire que c'est le pointeur c'est const
, pas la fonction)?
Concernant # 4: voir ce guide pour un aperçu utile de la création, de la transmission et de l’utilisation de pointeurs de fonction.
Sous C, il n’existe pas de fonction const
. const
est un qualificatif de type et ne peut donc être utilisé que pour qualifier un type, pas une fonction. Peut-être que vous voulez dire un pointeur const à une fonction ou un pointeur non-const à une fonction?
En C++, les méthodes peuvent être const
. Si une méthode est const
, cela signifie qu'après que vous avez appelé cette méthode, l'objet contenant la méthode sera dans le même état qu'avant l'appel de la méthode (aucune des variables d'instance [1] n'a été modifiée). Ainsi, vous pouvez pointer sur une méthode const et une méthode non-constante, et ces méthodes sont différentes.
Vous pouvez accepter un pointeur de fonction dans une liste d'arguments sous la forme retType (*variableName)(arguments)
.
[1] Sauf s'ils sont mutable
.
En C, les fonctions peut être const
si vous êtes dans le monde de GCC! Les fonctions peuvent être déclarées const
par l’utilisation d’attributs attachés aux déclarations de fonctions et autres symboles. Il est essentiellement utilisé pour fournir des informations au compilateur sur le fonctionnement de la fonction, même si son corps n'est pas disponible, afin que le compilateur puisse procéder à certaines optimisations.
Une fonction constante est généralement définie en termes d'une fonction pure
.
Une fonction pure est une fonction sans effets secondaires. Cela Signifie que les fonctions pures renvoient une valeur calculée en fonction de Paramètres et de la mémoire globale donnés, mais ne peuvent affecter la valeur d'aucune autre variable globale . Les fonctions pures ne peuvent raisonnablement manquer d’un type de retour (C’est-à-dire avoir un type de retour nul).
Et maintenant, nous pouvons définir ce qu'est une fonction const,
Une fonction pure qui n'accède pas à la mémoire globale, mais uniquement à ses paramètres , Est appelée fonction constante . En effet, la fonction , N'ayant aucun lien avec l'état de la mémoire globale, retournera toujours À la même valeur si les mêmes paramètres lui sont attribués. La valeur de retour Est donc déduite directement et exclusivement des valeurs des paramètres Donnés.
Ici, const
n'implique rien sur la mutabilité des fonctions. Mais c'est une fonction qui ne touche pas la mémoire globale. Vous pouvez affecter des pointeurs normaux à de telles fonctions. Quoi qu'il en soit, la région de code sera généralement (en oubliant pendant un certain temps le code à modification automatique) être RO et vous ne pouvez pas la modifier via le pointeur normal.
Lisez l'intégralité de l'article perspicace ici.
Donc quand il s’agit de Fonctions constantes GCC nous parlons d’optimisations et non de mutabilité de fonctions.
1. Il n’existe syntaxiquement aucun endroit où placer «const» pour rendre la fonction contenus constante.
Vous rencontrerez une erreur 'fonction n'est pas une valeur l', que vous ayez ou non const.
typedef void (* FUNC)(void);
FUNC pFunc;
pFunc = 0; // OK
*pFunc = 0; // error: Cannot assign to a function (a function is not an l-value)
typedef void (* const FUNC)(void);
FUNC pFunc;
pFunc = 0; // error (const)
*pFunc = 0; // error: Cannot assign to a function (a function is not an l-value)
typedef void (const * FUNC)(void); // error: <cv-qualifier> (lol?)
2 & 3. Pointeurs de fonction - oui .. Le contenu de la fonction ne ressemble pas.
4. Je ne pense pas qu'il soit possible de rendre le passage d'un pointeur de fonction plus sûr. Avec toutes les constantes du monde, la seule chose que vous puissiez protéger est que 'SetCallback' ne peut pas changer sa propre copie locale du paramètre.
typedef void (* const FUNC)(void);
void SetCallback(const FUNC const pCallback)
{
FUNC pTemp = pCallback; // OK (even though pTemp is not const!!)
pCallback = 0; // error (const)
}
1.Quelle est la signification d'un pointeur sur une fonction constante et d'un pointeur sur une fonction non constante?
Il n'y a pas de différence entre const et non-const: la fonction elle-même n'est pas modifiable
Remarque: En C++, si la fonction est une fonction membre d'une classe, const signifie que l'état de l'objet dans cette fonction ne peut pas être modifié (variables membres affectées à, fonctions memeber non-const appelées). Dans ce cas, le mot-clé const fait partie de la signature de la fonction membre et fait donc une différence en termes de pointeur.
2.Peut-on qu'une fonction soit constante?
Voir au dessus.
3.Peut-on qu'une fonction soit non-const (mutable)?
Voir au dessus
4.Quelle est la syntaxe correcte (sécurisée) pour passer un pointeur de fonction?
Tous les pointeurs vers des fonctions libres peuvent être convertis en n’importe quel pointeur vers une fonction libre (c’est-à-dire que leur taille est la même). Vous pouvez donc définir un type pour une fonction (hypothétique): void f();
et convertir tous les pointeurs de fonction de ce type à stocker. Remarque que vous ne devez pas appeler la fonction via ce type commun: vous devez lui attribuer le type de pointeur à fonction d'origine, sinon vous obtenez un comportement non défini (et probablement un crash).
Pour C++: il n'est pas garanti que les pointeurs vers les fonctions membres soient convertibles en pointeurs vers des fonctions libres