PpHd (./179) :
Kevin Kofler (./173) :
-> erreur (pas le droit de sauter dans la portée d'un VLA).
Ben oui. Mais ca le fait aussi sur les goto:
void f(int foo) {
if (foo != 1)
goto l2;
l1: ;
int n=3;
int x[n];
l2:
}
Je sais, faut éviter de faire n'importe quoi là aussi.
Mais à mon avis ca n'a rien à voir. Car on a la même chose avec le code suivant qui est clean:
if (error)
goto handle_error;
...
handle_error: ;
int my_error = errno;
...
Pour moi, c'est une lacune de la norme C.
C'est vrai que ça peut être lourd, et pour les labels normaux, l'astuce du ; peut être pratique (surtout s'il n'y a pas d'autre label derrière qui crée des problèmes de portée de la variable), mais dans un
switch, il vaut mieux des accolades à cause de cette histoire de portée.
Kevin Kofler (./173) :
Et pourquoi utilises-tu encore ce switch qui sert uniquement au portage de vieilles sources K&R? Pourquoi à ton avis ce switch n'est-il pas inclus dans -Wall ni -Wextra?
Parce que je veux que chacune de mes fonctions soit parfaitement prototypée ?
AMHA, ce que tu veux vraiment est -Werror-implicit-function-declaration, pas -Wmissing-prototypes. Ça ne sert à rien de prototyper une fonction quand sa définition fait déjà office de prototype.
Pour le second point, je ne sais pas, mais je sais que bon nombre de projets le rajoute.
Le switch n'est pas inclus dans -Wall ni -Wextra parce que ce n'est qu'une aide au portage (pour les projets qui passent des définitions de fonctions K&R aux prototypes C ISO) et ça sort des warnings totalement bidons pour du code parfaitement valide.
Kevin Kofler (./173) :
Fais un cast explicit vers (const int (*)[ 3]), c'est plus propre que ton aliasing violation.
C'est moins comode car si la taille de T augmente, où son type, tu dois corriger tous les cast.
Mais ta solution est incorrecte, tu ne respectes pas le strict aliasing. Tu ne peux pas ignorer les warnings sur le strict aliasing, l'optimisateur de GCC peut vraiment te pondre n'importe quoi si tu ne respectes pas l'aliasing, et même si ça marche maintenant, ça peut te faire boguer ton programme à tout moment.
Fais un autre
typedef pour la version pointeur de T.
Mais c'est encore une lacune de la norme C.
Les FAQs expliquent pourquoi c'est comme ça, tu peux contourner la constness en convertissant un
int ** en un
const int **. (En revanche, je ne suis pas sûr que l'exemple problématique fonctionne avec les
int [][].)
Tiens encore un truc en C:
#include <string.h>
typedef int T[3][3];
void f( T *x)
{
memset (x[0], 0, sizeof (x[0]));
memset (x[1], 0xAF, sizeof (x[1]));
memset (x[2], 0x6D, sizeof (x[2]));
}
Ce code est buggué. Pourquoi ?
Parce qu'un
T * est un
int (*)[3][3] qui se comporte comme un
int [foo][3][3]. (Facile.

)