Question

Supposons que j'ai une fonction

void foo(char *)

qui, intérieurement, doit traiter son entrée en tant que bloc de terminaison NUL-octets (par exemple, il est une fonction de hachage sur des chaînes). Je pourrais jeter l'argument unsigned char* dans la fonction. Je pourrais aussi changer la déclaration à

void foo(unsigned char *)

Maintenant, étant donné que char, signed char et unsigned char sont trois types différents de , serait-ce un changement constitue l'interface, en vertu de toute définition raisonnable du terme « interface » en C?

(Cette question est destinée à régler une discussion soulevée par une autre question. J'ai mes opinions, mais n'accepter une réponse jusqu'à ce que l'on vient comme un « gagnant » par les voix des autres.)

Était-ce utile?

La solution

Selon la norme ISO / IEC 9899: TC3,

  • appeler une fonction par une expression de type incompatible est un comportement non défini (6.5.2.2 §9)
  • types de fonctions compatibles doivent avoir des types de paramètres compatibles (6.7.5.3 §15)
  • types de pointeurs compatibles doivent pointer vers les types compatibles (6.7.5.1 §2)
  • char, signed char et unsigned char sont différents types de base (6.2.5) §14 et donc incompatibles (6.2.7 §1), qui est explicitement mentionnée dans la note 35 de la page 35

Alors oui, cela est clairement un changement à l'interface de programmation.

Cependant, comme char *, signed char * et unsigned char * aura des représentations identiques et les exigences d'alignement dans une mise en œuvre saine de langage C, l'interface binaire reste inchangé.

Autres conseils

Oui il est. Code client qui, auparavant, compilé ne sera plus compiler (ou de toute façon est susceptible de générer de nouveaux avertissements), donc ce changement est la rupture.

Je choisis « C - aucun des ci-dessus. »

Bien que ce n'est pas une réponse directe à la question que vous avez réellement demandé, la bonne solution à la situation semble assez simple et évident pour moi. Vous ne devriez pas vraiment utiliser l'une de ces

Au moins l'OMI, vous avez une très bonne raison de faire autrement, votre fonction doit accepter un void * ou (de préférence) void const *. Qu'est-ce que vous cherchez est essentiellement un pointeur opaque, et qui est exactement ce que void * fournit. L'utilisateur n'a pas besoin de savoir quelque chose sur le fonctionnement interne de votre mise en œuvre, et depuis tout autre type de pointeur se convertir en void * implicitement, il est l'un des rares possibilités qui ne rompt pas le code existant soit.

Est-ce qu'un char * convertir implicitement un unsigned char *?

  • Oui - vous avez pas cassé votre interface
  • Non - vous avez eu une fuite mise en œuvre
    détails.

Non, ce n'est pas. Toute modification de code client est trivial (surtout si elle est juste pour éviter un avertissement), et dans la pratique à peu près toute implémentation de C vous verrez que vous ne même pas besoin d'une nouvelle compilation parce que des pointeurs vers char* et unsigned char* seront passé exactement de la même façon dans la convention d'appel.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top