Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Enum, NULL et warning de votre compilo...

6 réponses
Avatar
Marc Boyer
Bonjour à tous,

pas une question de C, mais de test de warning de compilos.

Soit le code suivant:

typedef enum {x, y} Enum;
void foo(Enum* e){
e= x;
}

Bon, j'aimerais bien que le compilo palie à mon manque de
sommeil et me détecte l'erreur de type Enum* <- Enum
(genre warning: assignment makes pointer from integer without a cast).

Je viens de donner ça à mangger à mon gcc, et ça passe comme une
lettre à la poste avec la valeur x (parce que x, c'est 0, que
0, c'est NULL, et que donc, on peut...), avec pourtant les
options
-Wall -pedantic -W -O -Wuninitialized

Et vos compilos préférés, ils voient quelque chose ?

Et à votre avis, c'est un choix délibéré de gcc de ne rien dire
ou c'est un oublis ?

Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exciter des sots
IF -- Rudyard Kipling (Trad. André Maurois)

6 réponses

Avatar
Anthony Fleury
Bonjour à tous,


Bonjour,

pas une question de C, mais de test de warning de compilos.

Soit le code suivant:

typedef enum {x, y} Enum;
void foo(Enum* e){
e= x;
}

Bon, j'aimerais bien que le compilo palie à mon manque de
sommeil et me détecte l'erreur de type Enum* <- Enum
(genre warning: assignment makes pointer from integer without a cast).

Je viens de donner ça à mangger à mon gcc, et ça passe comme une
lettre à la poste avec la valeur x (parce que x, c'est 0, que
0, c'est NULL, et que donc, on peut...), avec pourtant les
options
-Wall -pedantic -W -O -Wuninitialized

Et vos compilos préférés, ils voient quelque chose ?


Pareil pour mes compilateurs ici (un compilateur pour cible embarquée et
Comeau C).

Et à votre avis, c'est un choix délibéré de gcc de ne rien dire
ou c'est un oublis ?


C'est un choix délibéré, ils n'ont pas, pour moi, le droit d'emettre un
warning, à cause de ceci :

6.2.3-3 : An integer constant expression with the value 0, or such an
expression cast to type void *, iscalled a null pointer constant. If a
null pointer constant is converted to a pointer type, the resulting
pointer,called a null pointer,isguaranteed to compare unequal
to a pointer to any object or function.

Ce qui fait qu'il est autorisé d'initialiser un pointeur comme pointeur
NULL avec :

int* p = 0; (1)
int* p = (int*) 0;
int* p = (void*) 0;

Donnant toujours le même résultat... Si jamais un compilateur émettait
un warning sur le code avec l'enum, il devrait en émettre un sur (1).
Pour obtenir un warning, reste plus qu'à faire
typedef enum {x=1, y} Enum;

Anthony

Avatar
Marc Boyer
On 2008-02-21, Anthony Fleury wrote:
Et à votre avis, c'est un choix délibéré de gcc de ne rien dire
ou c'est un oublis ?


C'est un choix délibéré, ils n'ont pas, pour moi, le droit d'emettre un
warning, à cause de ceci :


Tu sais, ils émettent les warnings qu'ils veulent. Le compilo
pourrait raler que Enum n'est pas un bon nom de type s'il voulait.

6.2.3-3 : An integer constant expression with the value 0, or such an
expression cast to type void *, iscalled a null pointer constant. If a
null pointer constant is converted to a pointer type, the resulting
pointer,called a null pointer,isguaranteed to compare unequal
to a pointer to any object or function.

Ce qui fait qu'il est autorisé d'initialiser un pointeur comme pointeur
NULL avec :

int* p = 0; (1)
int* p = (int*) 0;
int* p = (void*) 0;


Tout à fait.
On peut même faire
int* p= 0.0;
de là à dire que c'est une bonne idée.

Donnant toujours le même résultat... Si jamais un compilateur émettait
un warning sur le code avec l'enum, il devrait en émettre un sur (1).
Pour obtenir un warning, reste plus qu'à faire
typedef enum {x=1, y} Enum;


Sauf qu'en vrai, je fais un truc du genre
typedef enum {x, y, size_Enum } Enum;
qui me permet de faire des boucles du genre
for(Enum i=0 ; i < size_Enum ; ++i)
et des déclarations comme
const char* nom_Enum[size_Enum]= {"x", "y" };
que c'est assez classique, et que si les enums ne commencent
plus à 0, ça va devenir plus moche...

Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exciter des sots
IF -- Rudyard Kipling (Trad. André Maurois)


Avatar
Anthony Fleury
On 2008-02-21, Anthony Fleury wrote:
Et à votre avis, c'est un choix délibéré de gcc de ne rien dire
ou c'est un oublis ?
C'est un choix délibéré, ils n'ont pas, pour moi, le droit d'emettre un

warning, à cause de ceci :


Tu sais, ils émettent les warnings qu'ils veulent. Le compilo
pourrait raler que Enum n'est pas un bon nom de type s'il voulait.


En effet.
Par contre, je ne suis pas sûr qu'un compilateur pourrait (simplement)
émettre un warning dans le cas présenté et ne pas en émettre un dans le cas

int *p = 0;

Or, si un compilateur en émettait un pour ce type de construction, ca
risquerait de mettre des warnings dans pas mal de codes existant vu
qu'on peut définir NULL comme 0.

Me trompe-je ?

Anthony



Avatar
Antoine Leca
En news:, Marc Boyer va escriure:
typedef enum {x, y} Enum;
void foo(Enum* e){
e= x;
}

Bon, j'aimerais bien que le compilo palie à mon manque de
sommeil et me détecte l'erreur de type Enum* <- Enum
(genre warning: assignment makes pointer from integer without a cast).


Solution 1 : ne pas utiliser la valeur 0 comme signifiant (cela évite une
palanquée de problème de pointeurs non initialisé)

Solution 2 : passer à un langage plus moderne (la liste est trop longue)


Et vos compilos préférés, ils voient quelque chose ?


On oublie le « préféré », rabattons-nous sur le tout-venant...

SPLint le voit.
marc.c: (in function foo)
marc.c(5,3): Assignment of enum { x, y } to Enum *: e = x
Types are incompatible. (Use -type to inhibit warning)

Le compilo de Microsoft (version 5.1 de 1988) le voit (avec le niveau
d'avertisement par défaut).
marc.c(5) : warning C4047: '=' : different levels of indirection

OpenWatcom ne semble pas le voir.
Digital Mars non plus.
Borland non plus (mais j'ai pas été à la pêche aux options).


Antoine

Avatar
Marc Boyer
On 2008-02-21, Anthony Fleury wrote:
On 2008-02-21, Anthony Fleury wrote:
Et à votre avis, c'est un choix délibéré de gcc de ne rien dire
ou c'est un oublis ?
C'est un choix délibéré, ils n'ont pas, pour moi, le droit d'emettre un

warning, à cause de ceci :


Tu sais, ils émettent les warnings qu'ils veulent. Le compilo
pourrait raler que Enum n'est pas un bon nom de type s'il voulait.


En effet.
Par contre, je ne suis pas sûr qu'un compilateur pourrait (simplement)
émettre un warning dans le cas présenté et ne pas en émettre un dans le cas

int *p = 0;


Je pense que ça dépend beaucoup de où sont gérés les warnings
dans la chaine de compilation.

Or, si un compilateur en émettait un pour ce type de construction, ca
risquerait de mettre des warnings dans pas mal de codes existant vu
qu'on peut définir NULL comme 0.

Me trompe-je ?


C'est clair que ce serait un remède pire que le mal.

Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exciter des sots
IF -- Rudyard Kipling (Trad. André Maurois)




Avatar
Marc Boyer
On 2008-02-21, Antoine Leca wrote:
En news:, Marc Boyer va escriure:
typedef enum {x, y} Enum;
void foo(Enum* e){
e= x;
}

Bon, j'aimerais bien que le compilo palie à mon manque de
sommeil et me détecte l'erreur de type Enum* <- Enum
(genre warning: assignment makes pointer from integer without a cast).


Solution 1 : ne pas utiliser la valeur 0 comme signifiant (cela évite une
palanquée de problème de pointeurs non initialisé)


Voui, mais c'est assez idiomatique de faire des trucs du genre
typedef enum { x , y , size_Enum } Enum;
static const char name_Enum[size_Enum]= { "x", "y" };

Si on commence plus à 0, ça devient moins facile.
En plus, ça va être moins idiomatique, moins maintenable,
tout ça pour un bug assez rare je pense (et vite détecté lors
des tests).

Solution 2 : passer à un langage plus moderne (la liste est trop longue)


Sauf que là, je prépare un mini-projet de C.

Et vos compilos préférés, ils voient quelque chose ?


On oublie le « préféré », rabattons-nous sur le tout-venant...

SPLint le voit.
marc.c: (in function foo)
marc.c(5,3): Assignment of enum { x, y } to Enum *: e = x
Types are incompatible. (Use -type to inhibit warning)


Je l'avais oublié celui là.

Le compilo de Microsoft (version 5.1 de 1988) le voit (avec le niveau
d'avertisement par défaut).
marc.c(5) : warning C4047: '=' : different levels of indirection


OK

OpenWatcom ne semble pas le voir.
Digital Mars non plus.
Borland non plus (mais j'ai pas été à la pêche aux options).


Merci pour les infos.

Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exciter des sots
IF -- Rudyard Kipling (Trad. André Maurois)