OVH Cloud OVH Cloud

[HS] gcc et warning sur flexible array member

26 réponses
Avatar
Marc Boyer
Bon, juste une question HS: j'ai cherché sans trouver une
option de gcc pour détecter les flexible array member,
sans succès.

J'ai mal cherché ou il n'y en a pas ?

C'est pour mes pauv' étudiants qui écrivent
struct Vecteur {
size_t size;
double val[];
};
en lieu et place de
struct Vecteur {
size_t size;
double *val;
};

Marc Boyer
--
Je ne respecte plus le code de la route à vélo depuis une double fracture
due au fait que j'étais le seul à le respecter.

10 réponses

1 2 3
Avatar
Emmanuel Delahaye
Harpo wrote on 12/05/05 :
bool (ravi de faire sa connaissance) ça doit être bien, mais je m'en
passe encore.


Pareil

Les "tableaux flexibles", je m'en suis déjà servi sous gcc, ça marche
(au moins pour une utilisation triviale mais je n'ai pas poussé le
compilo dans ses retranchements). C'est en tout cas très utile.


Méfiance...

http://www.gnu.org/software/gcc/gcc-4.0/c99status.html

"variable-length arrays Broken "

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"Clearly your code does not meet the original spec."
"You are sentenced to 30 lashes with a wet noodle."
-- Jerry Coffin in a.l.c.c++

Avatar
Pierre Maurette
Pierre Maurette wrote:

En revanche, je ne sais trop que penser des facilités issues de C++,
présentes dans C99 et souvent admises en C(avec le bon commutateur, ou
en incluant le bon header). Je pense par exemple aux commentaires fin
de ligne //, aux bool, aux déclaration au sein du bloc.
Ce n'était pas le point qui m'importait le plus dans mon post, c'est


classique et ça m'apprendra à être aussi dactyloverbeux ;-)


// c'est très bien. Cela incite à mettre des commentaires.
Et un compilo qui n'est pas capable d'implémenter ça pour le lendemain
ne vaut pas la peine qu'on s'y attarde.
Et puis sur une base "fonction" ou "unité", c'est facile à corriger.


Je ne savais pas que l'on pouvais faire des déclarations au sein d'un
bloc, faudra que j'essaye, il est possible que je me demande ensuite
comment j'ai pu m'en passer, mais a priori en C ça a surtout un interet
théorique.
En fait, je pensais surtout à des trucs comme:

for(int i = 0; i < TAILLE; ++i)

Je pense qu'il y aurait eu des choses plus importantes à mettre dans la
norme.
Je ne pensais pas à l'évolution de la norme, mais à ce que permettent

les compilateurs quand on ne leur demande pas d'être "strict ANSI".

bool (ravi de faire sa connaissance) ça doit être bien, mais je m'en
passe encore.
Pour le bool, c'est un peu compliqué.

D'un coté, il n'y a pas de vrai type booléen, ni l'entier en C89, ni
__Bool en C99, ni celui de stdbool.h, ni bool en C++. Que le bool de
C++ soit natif n'en fait pas un vrai type booléen (sur lequel au moins
on ne pourrait appliquer que des opérateurs logiques).
D'un autre coté, j'aime bien séparer sémantiquemnt les entiers des
variables booléennes. Ça veut dire appliquer uniquement des opérateurs
arithmétiques (dont les bitwise) aux entiers, et logiques aux booléens.
Ça signifie également if(!VarBool) mais if(VarInt == 0).
Donc, je trouve logique de marquer cette séparation par un type. Pour
true et false, c'est différent. true pose un problème si on s'amuse à
l'utiliser en comparaison (OK, c'est stupide).


Les "tableaux flexibles", je m'en suis déjà servi sous gcc, ça marche
(au moins pour une utilisation triviale mais je n'ai pas poussé le
compilo dans ses retranchements). C'est en tout cas très utile.
On revient sur le fond de mon interrogation. Si c'est très utile, c'est

donc que le code en dépend profondément. Donc que la réutilisation du
code de la fonction dans C++Builder ou dans Visual Studio sera
impossible ou compliquée. Non ?

--
Pierre


Avatar
Harpo
Pierre Maurette wrote:

En fait, je pensais surtout à des trucs comme:
for(int i = 0; i < TAILLE; ++i)


Oui, ça clarifie le code.

D'un autre coté, j'aime bien séparer sémantiquemnt les entiers des
variables booléennes. Ça veut dire appliquer uniquement des opérateurs
arithmétiques (dont les bitwise) aux entiers, et logiques aux
booléens. Ça signifie également if(!VarBool) mais if(VarInt == 0).
Donc, je trouve logique de marquer cette séparation par un type.


Ok.

Pour
true et false, c'est différent. true pose un problème si on s'amuse à
l'utiliser en comparaison (OK, c'est stupide).


Je ne comprends pas, on peut comparer une variable qui peut être
true/false à une autre qui a les mêmes possibilités.



Les "tableaux flexibles", je m'en suis déjà servi sous gcc, ça marche
(au moins pour une utilisation triviale mais je n'ai pas poussé le
compilo dans ses retranchements). C'est en tout cas très utile.
On revient sur le fond de mon interrogation. Si c'est très utile,

c'est donc que le code en dépend profondément.


Pas nécessairement 'profondément', cela peut simplifier le code ce qui
est toujours bon à prendre, il serait étonnant qu'une application
dépende profondément de cette possibilité.

Donc que la
réutilisation du code de la fonction dans C++Builder ou dans Visual
Studio sera impossible ou compliquée. Non ?


Personnellement, je ne connais pas ces gens là, ils ne m'ont jamais fait
de remontrances au sujet de la manière dont j'écris mes programmes,
j'en conclue tout naturellement qu'ils doivent en être satisfaits.

--
Patrick.
http://patrick.davalan.free.fr/


Avatar
Pierre Maurette
Pierre Maurette wrote:
[...]

Pour
true et false, c'est différent. true pose un problème si on s'amuse à
l'utiliser en comparaison (OK, c'est stupide).


Je ne comprends pas, on peut comparer une variable qui peut être
true/false à une autre qui a les mêmes possibilités.
Mais parfois pas avec le résultat souhaité:



/* Borland C++ 5.6, ANSI (-A) -w, pas de warning*/
#include<stdio.h>

#define AFF_BOOL(a) printf("%s: ", ""#a"");if(a)printf("TRUEn");else
printf("FALSEn")
#define GASP printf("[Damned!] ")
typedef enum {false, true} bool;

int main(void)
{

bool A = true;
bool B = true;
B++; /* ou autre bêtise */
AFF_BOOL(A);
AFF_BOOL(B);
AFF_BOOL(!!B);
GASP;AFF_BOOL(A==B);
AFF_BOOL(A==!!B);
AFF_BOOL(A==true);
GASP;AFF_BOOL(B==true);
AFF_BOOL(A!úlse);
AFF_BOOL(B!úlse);
return 0;
}

Les "tableaux flexibles", je m'en suis déjà servi sous gcc, ça marche
(au moins pour une utilisation triviale mais je n'ai pas poussé le
compilo dans ses retranchements). C'est en tout cas très utile.
On revient sur le fond de mon interrogation. Si c'est très utile,

c'est donc que le code en dépend profondément.


Pas nécessairement 'profondément', cela peut simplifier le code ce qui
est toujours bon à prendre, il serait étonnant qu'une application
dépende profondément de cette possibilité.
On pinaille sur les mots.


Donc que la
réutilisation du code de la fonction dans C++Builder ou dans Visual
Studio sera impossible ou compliquée. Non ?


Personnellement, je ne connais pas ces gens là, ils ne m'ont jamais fait
de remontrances au sujet de la manière dont j'écris mes programmes,
j'en conclue tout naturellement qu'ils doivent en être satisfaits.
J'ai cité des IDE, mais c'est vrai des deux compilateurs sous jacents

(gratuits), qui sont avec gcc parmi les plus utilisés sous Windows.

--
Pierre



Avatar
Marc Boyer
Laurent Deniau wrote:
débutants, leur faire assimiler les VLA serait prématuré, mieux vaut
leur faire assimiler des choses comme la priorité des opérateurs du
langage C ou les pointeurs. Ils découvraient par eux-même les VLA
ainsi que les autres joyeusetés de C99.



Ben oui, dans mon cours, j'ai pas parlé des VLA. Mais là, je
corrige mes copies, et j'en ai plein qui utilise des VLA en
croyant utiliser un pointeur. Et le compilo a rien dit, puisque
c'est du C99.


Tu parles de VLA ou de flexible array. C'est deux choses differentes.
Ton exemple parle bien de flexible array (note pour les reponses des
posts suivants) qui sont supportes par la pluspart des compilos pre-C99.


Pardon, flexible array, je me suis laissé enduire d'erreur par le
post auquel je répondais.

Pour les VLA c'est autre chose.


Tout à fait.

Reste l'option C89 + #include <boyerbool.h>

typedef enum {true=1, false=0} bool;


Definition incompatible avec c99...


Ca m'avait échappé.
Et si on fait un
#if __STDC_VERSION__ >= 199901L
#include <stdbool.h>
#else
typedef enum {true=1, false=0} bool;
#endif
on a quand même des problèmes ?

Un enum est de type int. int a un rank plus grand que char et short.
Donc au mieux, mais toujours pas correct, tu peux definir _Bool (ou
bool) comme un unsigned char. Ceci dit, c'est aussi incompatible avec
c99 puisque:

6.7.2.1-4
A bit-field shall have a type that is a qualified or unqualified version
of _Bool, signed int, unsigned int, or some other implementation-defined
type.

Fait ton choix d'incompatibilite camarade ;-). Moi j'ai choisi d'etre
compatible avec le rank parce que je prohibe les bit-field et qu'un
tableau de bool est plus petit si c'est un unsigned char.

Dernier point, pour convertir un integral type en bool, il faut faire
!!value (on dirait du Eiffel ;-) )


Oui, dur...

Marc Boyer
--
Je ne respecte plus le code de la route à vélo depuis une double fracture
due au fait que j'étais le seul à le respecter.



Avatar
Marc Boyer
Stephane Zuckerman wrote:
Je ne pense pas. Ce qui est défini par C89 est encore valable pour
beaucoup de choses. D'autre part, si tes élèves sont complètement
débutants, leur faire assimiler les VLA serait prématuré, mieux vaut
leur faire assimiler des choses comme la priorité des opérateurs du
langage C ou les pointeurs. Ils découvraient par eux-même les VLA
ainsi que les autres joyeusetés de C99.


Ben oui, dans mon cours, j'ai pas parlé des VLA. Mais là, je
corrige mes copies, et j'en ai plein qui utilise des VLA en
croyant utiliser un pointeur. Et le compilo a rien dit, puisque
c'est du C99.
Reste l'option C89 + #include <boyerbool.h>

typedef enum {true=1, false=0} bool;
Honnêtement, si ce n'est pas en cours qu'on apprend le C99, comment

espérez-vous répandre son utilisation ?


Commençons par dire que je n'ai pas pour but de promouvoir
C99 mais d'aider mes élèves à faire du code C robuste et portable.
Une partie de C99 va dans ce sens.

Sans forcément faire un cours sur les VLA, mentionner leur existence, à
quoi ils servent, etc. serait bénéfique. Par exemple, vous donnez les
bases nécessaires au cours de programmation, et lorsque celles-ci
(tableaux, pointeurs, passage par valeur, et tutti quanti) sont assimilés,
consacrer un cours aux spécificités que vous n'avez pas (eu) le temps
d'aborder me semble utile.


Oui, si on me donne 2h de cours de plus, et les heures de TD/TP qui
vont avec, je peux faire des choses en plus. M'enfin avant les
flexible array et les VLA, je pense que je m'occuperais d'E/S.

Dans mes cours de C, à l'époque, nous avons découvert l'utilisation
d'opérateurs "raccourcis" (+=, ++, test?a:b ,etc.) relativement tard dans
le cursus.


Mes ces notations ne sont que des raccourcis pour des notions
basiques. Alors que flexible array et VLA sont des notions
différentes, pas des notations.

Marc Boyer
--
Je ne respecte plus le code de la route à vélo depuis une double fracture
due au fait que j'étais le seul à le respecter.



Avatar
Laurent Deniau
Marc Boyer wrote:
Laurent Deniau wrote:
Reste l'option C89 + #include <boyerbool.h>

typedef enum {true=1, false=0} bool;


Definition incompatible avec c99...



Ca m'avait échappé.
Et si on fait un
#if __STDC_VERSION__ >= 199901L
#include <stdbool.h>
#else
typedef enum {true=1, false=0} bool;


pourquoi tu fais pas simplement:

typedef enum { false, true } bool;

?

#endif
on a quand même des problèmes ?


non puisqu'on a pas de bool en C89.

Par contre, un programme compile en C89 puis en C99 peut avoir un
comportement different. Si tu veux le comportement le plus proche (a
l'exception des bit-fields) il vaut mieux utiliser un unsigned char. Par
exemple sur gcc, sizeof(bool) == 1...

Un enum est de type int. int a un rank plus grand que char et short.
Donc au mieux, mais toujours pas correct, tu peux definir _Bool (ou
bool) comme un unsigned char. Ceci dit, c'est aussi incompatible avec
c99 puisque:

6.7.2.1-4
A bit-field shall have a type that is a qualified or unqualified version
of _Bool, signed int, unsigned int, or some other implementation-defined
type.

Fait ton choix d'incompatibilite camarade ;-). Moi j'ai choisi d'etre
compatible avec le rank parce que je prohibe les bit-field et qu'un
tableau de bool est plus petit si c'est un unsigned char.

Dernier point, pour convertir un integral type en bool, il faut faire
!!value (on dirait du Eiffel ;-) )



Oui, dur...


J'aimais bien C89, c'etait moins complet donc c'etait moins confus ;-)

a+, ld.



Avatar
Marc Boyer
Stephane Zuckerman wrote:
Reste l'option C89 + #include <boyerbool.h>

typedef enum {true=1, false=0} bool;
Honnêtement, si ce n'est pas en cours qu'on apprend le C99, comment

espérez-vous répandre son utilisation ?


D'ailleurs, hormis bool et le %z, en y réfléchissant bien,
je ne vois pas d'intérêt flagrant à enseigner C99 au lieu
de C89...

Marc Boyer
--
Je ne respecte plus le code de la route à vélo depuis une double fracture
due au fait que j'étais le seul à le respecter.


Avatar
Richard Delorme
Stephane Zuckerman wrote:

Reste l'option C89 + #include <boyerbool.h>

typedef enum {true=1, false=0} bool;


Honnêtement, si ce n'est pas en cours qu'on apprend le C99, comment
espérez-vous répandre son utilisation ?



D'ailleurs, hormis bool et le %z, en y réfléchissant bien,
je ne vois pas d'intérêt flagrant à enseigner C99 au lieu
de C89...


J'aime bien __VA_ARGS__ et __func__, qui aide pas mal au débogage. Je
suppose que les gens qui en ont l'utilité doivent apprécier les
complexes et un meilleur support des mathématiques. Pour les flexible
array member, j'ai comme un doute, mais il s'agit d'une normalisation de
pratiques existantes, donc certains doivent apprécier.

--
Richard



Avatar
Antoine Leca
En <news:d61ni7$h93$, Marc Boyer va escriure:
Laurent Deniau wrote:
Reste l'option C89 + #include <boyerbool.h>

typedef enum {true=1, false=0} bool;


Definition incompatible avec c99...


Ca m'avait échappé.


Comment fais-tu pour respecter la règle:


6.3 Conversions

6.3.1.2 Boolean type
[1] When any scalar value is converted to *_Bool*, the result is 0
if the value compares equal to 0; otherwise, the result is 1.

Autrement dit, en C99,

_Bool B;

B = 0; /* false */
B++; /* true */
B++; /* B inchangé, vaut toujours 1 ! */
B = B+1; /* idem, B inchangé, vaut toujours 1 ! */

1+B est un int car B est promu (rang plus faible, comme expliquait Laurent);
le résultat de l'addition est donc 2; ensuite il s'agit de stocker le
résultat dans B, donc il y a conversion, donc application de la règle
ci-dessus...

... pas facile à réaliser avec un compilateur C89, n'est-ce-pas?


Et si on fait un
#if __STDC_VERSION__ >= 199901L
#include <stdbool.h>
#else
typedef enum {true=1, false=0} bool;
#endif
on a quand même des problèmes ?


Cela dépend de ce que tu entends par problème(s).
Je trouve que le comportement ci-dessus est suffisament non intuitif (quand
on a été élevé dans l'idée que les booléens sont en fait des entiers) pour
générer des problèmes si on essaye de faire semblant que « c'est pareil ».


Antoine



1 2 3