web-dev-qa-db-fra.com

Dans une macro GNU C envSet (nom), que signifie (void) "" name?

Je suis tombé sur cette syntaxe aujourd'hui et je n'ai pas pu comprendre ce que cela signifiait:

// Uses the GNU C statement expression extension
#define envSet(name) ({ \
static int initialised; \
static bool set; \
(void) "" name; \
if (!initialised || !g_cacheEnv) { \
    const char *value = getenv(name); \
    set = value != NULL; \
    initialised = true; \
} \
set; \
})

La ligne spécifique que je ne peux pas comprendre est:

(void) "" name; \

Quelqu'un pourrait-il nous éclairer à ce sujet?

65
OMGtechy

Cela ressemble à un moyen de garantir statiquement que name est un littéral de chaîne et non un autre type.

Si tu fais (void)"" "hello"; alors c'est une expression C valide.

Mais si vous faites quelque chose comme (void)"" 1; alors vous obtenez une erreur de syntaxe.

76
Lundin

Deux littéraux de chaîne consécutifs sont concaténés. Vraisemblablement, il vérifie si name est un littéral de chaîne. Si ce n'est pas le cas, le compilateur signalera une erreur.

(void) cast supprimera les avertissements tels que "instruction sans effet".

45
milleniumbug

En regardant le code, je crois que le but est de le faire appeler getenv la première fois qu'il est appelé, mettre en cache le résultat, puis utiliser le résultat mis en cache sans avoir à appeler getenv . Si getenv est utilisé avec un littéral de chaîne, tous les appels suivants demanderont la même variable d'environnement; si rien ne pouvait changer cette variable d'environnement, ils retourneraient par conséquent le même résultat. Si le code recevait un pointeur sur une chaîne qui a changé par la suite, le résultat mis en cache ne serait probablement pas correct pour la nouvelle chaîne, donc le but de l'astuce "" est de s'assurer que cela ne peut pas se produire.

Étant donné que chaque littéral de chaîne qui pourrait être utilisé devrait avoir sa propre variable statique qui lui est associée, l'extrait de code indiqué ne peut pas raisonnablement être transformé en fonction. D'un autre côté, la quantité de code nécessaire pour chaque répétition semble un peu trop. En outre, si la même variable est testée à plusieurs endroits dans le code, chacun pourrait se retrouver avec son propre ensemble de variables et son code de vérification de l'environnement.

Selon la façon dont la fonction sera utilisée, elle peut finir par être beaucoup plus rapide que le code qui doit tester une variable d'environnement à chaque appel, et elle peut être utilisable à partir d'une fonction appelée dans une boucle sans configuration préalable (si code client appelé fonction de "configuration avancée", la recherche de nom doit y être effectuée, ce qui élimine la nécessité de vérifier dans la boucle si la recherche a été effectuée).

7
supercat