web-dev-qa-db-fra.com

Fonction définie mais pas utilisée d'avertissement en C

J'ai un certain nombre de fichiers source C (fichiers .c et .h). les fichiers d'en-tête contiennent un certain nombre de fonctions. Parmi ces fonctions, elles ne sont utilisées que partiellement dans un fichier .C source.Supposons a.h, b.h sont des fichiers d'en-tête et a.c et b.c sont des fichiers .c. a.h est inclus dans a.c. Mais seulement un certain nombre de fonctions se trouvent dans a. h sont utilisés et repos ne sont pas utilisés. Après la compilation, je trouve les avertissements suivants:

 function XXXX defined but not used.

Mais les fonctions XXXX qui ne sont pas utilisées dans a.c sont utilisées dans b.c. Donc, je ne peux pas supprimer complètement ces fonctions aussi. J'ai donc décidé de créer un fichier séparé contenant uniquement ces fonctions XXXX et de l'inclure partout où il est utilisé, ce qui crée plusieurs nombres de fichiers d'en-tête. Quelqu'un peut-il me suggérer un moyen efficace de résoudre ce problème.

30
thetna

L'avertissement "Fonction définie mais non utilisée" n'est émis que pour les fonctions avec liaison interne, c'est-à-dire les fonctions déclarées comme static. Ces fonctions ne sont accessibles que dans une seule unité de traduction, donc le compilateur sait toujours si elles sont utilisées (dans le programme) ou non. Si vous ne faites pas référence à ces fonctions dans leur unité de traduction, ces fonctions sont connues pour être inutilisées et l'avertissement est généré.

Vous dites que ces fonctions "ne sont pas utilisées en a.c, mais utilisées en b.c". Ce n'est pas vrai. Lorsque vous déclarez (et définissez) une fonction comme static dans le fichier d'en-tête, chaque unité de traduction qui inclut ce fichier d'en-tête obtient son propre --- copie interne de la fonction. Même si ces fonctions sont absolument identiques, ce sont toujours des fonctions distinctes et complètement indépendantes. Le fait qu'ils portent le même nom et se composent du même code ne signifie rien pour le compilateur. Donc, dans b.c, Vous avez une copie complètement indépendante de la fonction, qui est utilisée (comme vous le dites), mais la copie complètement indépendante dans a.c N'est toujours pas utilisée.

La question dans ce cas est pourquoi vous faites cela. Pourquoi diable définissez-vous des fonctions statiques dans le fichier d'en-tête? Si vous avez vraiment besoin de faire cela (c'est-à-dire si vous voulez vraiment générer un "clone" interne séparé de cette fonction dans chaque unité de traduction), vous pouvez contourner l'avertissement en utilisant des moyens spécifiques au compilateur. Comme dans GCC, par exemple, vous pouvez déclarer la fonction avec __attribute__((unused)) et l'avertissement pour cette fonction ne sera plus émis.

Mais normalement, il n'est pas nécessaire de définir des fonctions dans le fichier d'en-tête. Normalement, on utilise une fonction avec une liaison externe (c'est-à-dire pas de static), la définissez dans l'un des fichiers .c et placez la déclaration (prototype) dans le fichier d'en-tête. Le compilateur n'émettra aucun avertissement dans ce cas, même si la fonction est déclarée mais n'est pas utilisée dans une unité de traduction.

70
AnT

Si vous souhaitez simplement masquer l'avertissement, utilisez:

-Wno-unused-function

Cependant, vous devriez probablement suivre les conseils de réponse de caf à la place. Il semble que vous ayez défini une fonction lorsque vous vouliez seulement ajouter sa déclaration.

8
thomasrutter

Au lieu de "ne pas faire ça", considérez ce qui suit - un ensemble de fonctions qui déclenchera jusqu'à trois avertissements de fonction inutilisés.

static int get_version_number(void) { return 42; }
static double hidden_global_variable(void) { return 3.14; }
static int potential_alternative_to_macro(int x) { return 4 * x; } 

Écrivez une autre fonction, probablement basée sur le nom du fichier d'en-tête,

static void wno_unused_myheadername(void)
{
  /* don't need to actually call the functions to avoid the warnings */
  (void)&get_version_number;
  (void)&hidden_global_variable;
  (void)&potential_alternative_to_macro;
  return;
 }

Nous en sommes maintenant à un seul avertissement de fonction inutilisé. Si vous ajoutez un appel à wno_unused_myheadername () dans l'une des fonctions externes déclarées dans le fichier qui inclut l'en-tête, l'ensemble des avertissements de fonction inutilisés disparaîtra. Puisqu'ils sont maintenant tous utilisés.

Le compilateur supprimera n'importe où de toutes les fonctions inutilisées, y compris le wno_unused_myheadername, car il peut voir toutes les définitions et peut probablement déterminer que l'appel unique à la fonction wno_unused ne fait rien.

J'ai vérifié que ce qui précède supprime les avertissements comme prévu sous clang et gcc, votre kilométrage peut varier avec d'autres compilateurs. Je n'ai pas regardé la sortie asm pour savoir quand les fonctions presque inutilisées sont supprimées.

Quant à savoir pourquoi - une bonne raison serait d'utiliser beaucoup de petites fonctions qui sont bien adaptées à l'inline dans C89, qui n'a pas le mot clé inline, sans nécessiter l'optimisation du temps de liaison de votre compilateur.

8
Jon Chesterfield

Une autre possibilité consiste à définir ces fonctions comme inline au lieu de static. Dans ce cas, ils doivent être définis dans l'en-tête afin que la définition soit visible partout où ils sont appelés.

Le compilateur insérera le code à chaque endroit où la fonction est utilisée, alors faites attention à ce que vous vouliez vraiment. Voici une réponse avec une belle discussion sur ces compromis.

5
coombe

Il semble que votre problème est que vous définissez les fonctions dans .h des dossiers. Ne fais pas ça. Au lieu de cela, placez simplement vos déclarations dans le .h fichier, et avoir un .c fichier contenant les définitions des fonctions:

common.h:

#ifndef _COMMON_H
#define _COMMON_H

int foo(int a, int b);

int bar(double x, double y, double z);

#endif /* _COMMON_H */

common.c:

#include "common.h"

int foo(int a, int b)
{
    /* code */
}

int bar(double x, double y, double z)
{
    /* code */
}

Alors votre a.c et b.c devrait #include "common.h", et vous devrez vous arranger pour avoir common.c compilé dans le programme complet.

4
caf