Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

GCC doit émettre des warnings pour des usages de l'opérateur xor comme 2^16, 2^32, 2^64 qui prêtent à confusion,
D'après des utilisateurs

Le , par Patrick Ruiz

210PARTAGES

19  0 
Dans bon nombre de langages de programmation dont le C et le C++, l’opérateur ^ ne fait pas référence à celui d’exponentiation, mais au OU exclusif. Il vient alors qu’après évaluation, une expression comme 2^16 donne non pas 65 536, mais 18. Des exemples d’utilisation de cet opérateur foisonnent sur la toile et certains peuvent prêter à confusion pour qui lit (ou écrit) du code.

Code C : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
tp->tv_sec  = attributes[0] / 10^9; 
tp->tv_nsec = attributes[0] % 10^9; 
  
range->pmin[TREND_FCT] = -10^10; 
range->pmax[TREND_MEAN] = 10^10; 
  
#define IRQ_CHINT5_LEVEL        (12 ^ 7) 
#define IRQ_CHINT4_LEVEL        (11 ^ 7) 
#define IRQ_CHINT3_LEVEL        (10 ^ 7) 
#define IRQ_CHINT2_LEVEL        (9 ^ 7) 
#define IRQ_CHINT1_LEVEL        (8 ^ 7)


Code C : Sélectionner tout
1
2
3
4
5
read_bytes(&f, (char *) &(val), 
                   ( (n < (2 ^ 8))  ? 1 : 
                     ( (n < (2 ^ 16)) ? 2 : 
                       ( (n < (2 ^ 24)) ? 3 : 
                         4 ) ) ) );

« GCC n’émet pas d’avertissement pour : short maxshort = 2^16;, int maxint = 2^32; long maxlong = 2^64; Il faut que ce soit le cas en C et en C++. Je ne vois pas de raison valable d'écrire 2^16 quand vous voulez dire 18 ou 10^9 quand vous voulez dire 3, donc c'est probablement un bogue », a lancé Jonathan Wakely sur la liste de diffusion de bugs de GCC. « Mon Dieu que de faussetés en une seule ligne de code », a réagi un internaute sur un tweet d’un des participants aux échanges sur la liste de diffusion dédiée à GCC. En fait, l’un des problèmes avec cette ligne de code est qu’étant donné que l’expression 2^32 est évaluée en considérant l’opérateur ^ comme un OU exclusif, il vient que la boucle n’aura pas le nombre d’itérations auquel le rédacteur du code s’attend.


Si des tiers ont beaucoup plus remonté les cas d’ambiguïté qui se posent avec ce qui s’apparente de prime abord à des exponentiations de base 2, il faut dire que le problème reste le même avec les autres bases. Cet état de choses complexifie la détermination de l’angle sous lequel l’avertissement à générer sous GCC doit être orienté.

« Je pense que les avertissements doivent porter sur les cas où les deux opérandes sont des nombres entiers. Seulement, peut-on traiter tous les entiers sur un pied d’égalité ? Est-ce que 0x11 ^ 0b0011 est faux ? En tout cas, ça ne l’est pas de façon aussi évidente que 2^8 et 2^32. Est-ce que ces erreurs n'arrivent qu'aux puissances de 2 et 10 ? Est-ce que ça vaut la peine d'avertir à propos de 3^4 ? Après d'autres recherches, je ne suis même pas sûr que 10^ soit assez commun pour m'inquiéter. Peut-être que le compilateur ne devrait générer un avertissement que pour les cas qui s’apparentent à une exponentiation de base 2. Amener GCC à générer un avertissement pour ces situations que l’on pourrait considéré comme une exponentiation dans laquelle la base et l’exposant sont égaux semble également faire sens. Cela pourrait permettre de mettre la main sur des cas comme 10^10, mais pas sur – 10^10 », a ajouté Jonathan Wakely.

Les discussions battent leur plein sur la liste de diffusion GCC. Quelque soit le consensus sur lequel elles vont déboucher, il ne faut pas perdre de vue qu’il s’agit seulement d’étendre les capacités du compilateur générer des avertissements pour des cas de figure précis. En général, les compilateurs sont dotés d’options d’activation ou de désactivation des avertissements, ce qui fait que l’utilisateur n’est pas dans l’obligation de subir un en particulier.

Source : liste de diffusion GCC

Et vous ?

Qu’en pensez-vous ?
Êtes-vous en accord avec la nécessité que GCC génère ce warning ? Si oui, quels sont d’après vous les axes les plus pertinents ?
En tombant sur une ligne de code C comme for (int i = 0 ; i < = ( 2^32) – 1 ; i++) {} avez-vous au premier regard le sentiment qu’il y a une erreur qui s’est glissée ?

Voir aussi :

La version 9.1 du compilateur GCC est disponible et prend en charge le C++17, plusieurs autres fonctionnalités sont ajoutées

GCC 9 sera la première version stable du compilateur à supporter le langage D, un nouveau front-end allonge la liste

GCC 8.1 est disponible, la nouvelle version majeure du compilateur libre vient avec un support expérimental de C++2a et d'autres fonctionnalités

GCC 8.2 est disponible. Cette mise à jour du compilateur libre corrige une centaine de bogues

GCC : la version 7.3 du compilateur libre est disponible avec des correctifs pour la vulnérabilité Spectre pour les dispositifs x86 et powerpc

Une erreur dans cette actualité ? Signalez-le nous !

Avatar de TheLastShot
Membre extrêmement actif https://www.developpez.com
Le 18/06/2019 à 20:30
Et l'opérateur | est utilisé pour le "ou binaire" alors qu'en ligne de commande il sert de "pipe" pour chaîner les instructions... Il y a aussi le "%" qui est utilisé pour faire un modulo au lieu de calculer un pourcentage.... Il va lancer une alerte sur tous les opérateurs qui ne correspondent pas l'usage auquel il s'attend ?
Quand on connait le langage, ça ne prête absolument pas à confusion, sinon c'est qu'on connait pas le langage et en particulier ses opérateurs de base...
4  0 
Avatar de SimonDecoline
Membre expert https://www.developpez.com
Le 18/06/2019 à 22:14
Citation Envoyé par Patrick Ruiz Voir le message
Dans bon nombre de langages de programmation dont le C et le C++, l’opérateur ^ ne fait pas référence à celui d’exponentiation, mais au OU exclusif
...
peuvent prêter à confusion
...
Je suis d'accord, d'autant plus dans des projets qui utilisent plusieurs langages. Mais il existe déjà une solution : https://en.cppreference.com/w/cpp/la...or_alternative. Perso, j'ai quasiment banni && || ! de mes codes au profit de and or not.
3  0 
Avatar de lsbkf
Membre habitué https://www.developpez.com
Le 19/06/2019 à 1:12
Quand on fait du C, on part déjà du principe qu'on est dans un langage bas niveau et que l'exponentiation n'est pas une opération élémentaire. Même pour la division et le modulo, qui sont beaucoup plus courants, je connais des gens qui militent contre leur utilisation, surtout si le diviseur est une variable ou que c'est compilé pour du ARM.

Je pense que les gens qui font cette erreur ont raté leur vocation ou n'en ont rien à foutre. Ce n'est pas le seul langage à utiliser ^ pour le XOR, ce n'est pas le seul opérateur qui a des significations différentes sur des langages différents, il y a aussi des fonctions qui ne donnent pas le même résultat partout, et même les mot-clés ne sont pas à l'abri.
3  0 
Avatar de AoCannaille
Membre émérite https://www.developpez.com
Le 18/06/2019 à 18:29
Qu’en pensez-vous ?
Êtes-vous en accord avec la nécessité que GCC génère ce warning ? Si oui, quels sont d’après vous les axes les plus pertinents ?
J'en pense qu'il y a des erreurs plus courantes à améliorer dans gcc avant celle là que je n'ai jamais rencontré encore.
Je pense en particulier au fait de déclarer une fonction avec un type de retour, mais sans le mot clef return. Ceci ne génère qu'un warning et pas une erreur de compilation, c'est parfaitement stupide...
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
int superFonction(int& superArgument)
{
    superArgument++,
}

int main(int argc, char ** argv)
{
    int i = 0;
    printf("be amazed: %d", superFonction(i));

    return 0;
}
Cela va afficher ce qu'il y avait en mémoire dans l'emplacement mémoire prévue pour la variable retournée dans la fonction. Emplacement non initialisé (sauf en débug) qui va donc générer des cas incohérents en release...

Je ne comprend pas pourquoi cela existe encore, on a un mot clef clair quand on ne veut pas de return dans notre fonction : void. Ils devraient l'utiliser

En tombant sur une ligne de code C comme for (int i = 0 ; i < = ( 2^32) – 1 ; i++) {} avez-vous au premier regard le sentiment qu’il y a une erreur qui s’est glissée ?
Je ne suis jamais tombé sur ce cas, peut être que je ne code pas assez bas niveau pour m'amuser avec les masques de bits.
En tout cas, comme je n'ai pas l'habitude de voir de '^', je me serai posé la question. Sans remettre en cause le code, je serai allé vérifié ça sur le net ou en local sur un projet type hello world.
2  0 
Avatar de transgohan
Expert éminent https://www.developpez.com
Le 19/06/2019 à 8:50
Êtes-vous en accord avec la nécessité que GCC génère ce warning ? Si oui, quels sont d’après vous les axes les plus pertinents ?
Comme d'autres intervenants je ne trouve pas que cela soit nécessaire.
Si on fait le parallèle avec une fonction qu'on appellerai add() et qui permettrai d'ajouter un élément dans un tableau on pourrait très bien imaginer dans un langage qu'elle l'ajoute en début et dans un autre à la fin...
Dans tout langage il faut connaître les fonctions et leur fonctionnement.
Le xor est une fonction.

Précisons que Jonathan Wakely est un membre émérite de la team GCC ainsi que du comité de normalisation C++, contributeur très respecté de Stack overflow : il convient de réfléchir à deux fois avant de balayer ses propos d'un revers de main
C'est pourtant ce que je fais, sans être un membre émérite de quoi que ce soit.
Car ma pensée me semble logique, davantage que la sienne.
Il voit un bug là où je ne vois qu'une personne qui ne connait pas la norme du langage (j'exagère bien sûr car je me doute qu'il la connait davantage que moi).
Le compilateur est là pour valider qu'on applique la norme. Pas pour deviner ce que l'on voulait écrire.
2  0 
Avatar de walfrat
Membre actif https://www.developpez.com
Le 19/06/2019 à 9:00
Je suis contre.

Pour peu qu'on suive ne serait-ce qu'un tuto de base sur le net pour apprendre le langage, on apprend les opérateurs, opérateurs qui ont tendance à être les même dans beaucoup de langages puisqu'ils s'inspirent les un des autres..

Si des personnes qui n'ont pas les bases se retrouve à faire du C/C++ et qu'ils ne testent pas le bon fonctionnement de leur code (ben oui si tu test, ça se voit que ça marche pas), c'est pas la faute de GCC.
2  0 
Avatar de transgohan
Expert éminent https://www.developpez.com
Le 19/06/2019 à 13:46
Citation Envoyé par Aurelien.Regat-Barrel Voir le message
Mon Dieu, que d'exemples de réactions typiques de la culture du mépris
[...]
Donc quand ce genre de personne propose un changement dans le langage, en général, il y a une certaine idée derrière qu'il faut prendre le temps de comprendre.
Quand on parle de culture du mépris...
On a tout à fait le droit de ne pas être d'accord avec ce monsieur, et ce peu importe sa pensée.
Cela ne fait pas de nous des abrutis...
A bon entendeur.
2  0 
Avatar de stardeath
Membre expert https://www.developpez.com
Le 19/06/2019 à 17:40
Citation Envoyé par Aurelien.Regat-Barrel Voir le message
Le point soulevé est pourtant simple : quel intérêt d'écrire 2^16 quand on a besoin de la valeur 18? Il ne s'agit pas de bannir l'utilisation du XOR, il s'agit d’émettre un warning dans des cas d'utilisation louches. Où est le problème ? GCC émet déjà tout un tas de warnings du genre, comme par exemple:
l'intérêt? le même que quand tu écris 1<<3 à la place de 8 ou 0xdeadbeef à la place de 3735928559, parce que dans le contexte d'écriture de ces morceaux de code, tu identifies plus facilement les erreurs avec 1<<3 ou 0xdeadbeef qu'avec 8 et 3735928559.
un code dépend toujours minimum d'un contexte, et ça, un compilateur, comme le mentionne d'autres personnes, n'a pas la conscience des ces contextes, il n'est pas dans la tête des gens.
donc mettre un warning comme ton exemple avec un if sans accolade et un code trop indenté, pourquoi pas, autant là mettre un warning pour dire que dans certains cas "attention cet opérateur ^ à cet endroit n'est pas la mise à la puissance" me semble contre productif.

le problème avec la multiplication de ces warnings, c'est la multiplication des faux-positifs ou pire des lignes de commandes à rallonge pour désactiver tous les warnings, et je trouve que c'est un problème pire que celui soulevé dans ce fil.
pour ajouter à ça, les warnings c'est spécifiques au compilo, et écrire du code correct (point de vu norme) est déjà pas simple, si en plus tu dois avoir un code sans warning et multi plateforme, bonjour la cata.

après un autre problème, quand tu cites le palmarès de ce monsieur, ça s'appelle un argument d'autorité, et vu ce qui est sortie du comité c++ comme incohérences ces dernières années (incohérences critiquées même par d'autres sommités genre Sutter ou Stroustrup, j'en parle dans d'autres fils, je vais pas me répéter ici), il serait plutôt bon de les challenger, ceux qui vont devoir subir ce qu'ils décident, c'est nous, pas eux.
2  0 
Avatar de Pyramidev
Expert confirmé https://www.developpez.com
Le 20/06/2019 à 17:39
Citation Envoyé par AoCannaille Voir le message
j'ai croisé une surcharge de operator(), tout ça pour économiser un getter... L'appel ressemble à un constructeur, c'est assez troublant, mais même ça au final, est-ce que ça mérite un warning?
Quand une classe n'a qu'une seule opération importante, c'est normal de surcharger operator(). Il faut cependant veiller à ce que le nom de la classe soit suffisamment clair pour que l'on sache ce que fera operator().

Quand on utilise <algorithm> de la bibliothèque standard, quand on veut personnaliser un prédicat ou un critère de comparaison, on passe souvent par une classe qui surcharge operator().

Quand on veut mettre un objet dans un std::function, il faut que l'objet appartienne à une classe qui surcharge operator().
2  0 
Avatar de Aurelien.Regat-Barrel
Expert éminent sénior https://www.developpez.com
Le 18/06/2019 à 23:21
Citation Envoyé par AoCannaille Voir le message
Je pense en particulier au fait de déclarer une fonction avec un type de retour, mais sans le mot clef return. Ceci ne génère qu'un warning et pas une erreur de compilation, c'est parfaitement stupide...
c'est stupide si le C impose de ne pas compiler un tel code, autrement c'est juste être conforme avec la norme. Accessoirement, il suffit de compiler avec `-Werror` pour régler le problème.

Précisons que Jonathan Wakely est un membre émérite de la team GCC ainsi que du comité de normalisation C++, contributeur très respecté de Stack overflow : il convient de réfléchir à deux fois avant de balayer ses propos d'un revers de main
1  0