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

(Pour experts) Problème de syntaxe dans un switch()

14 réponses
Avatar
Patrick 'Zener' Brunet
Bonjour.

Ce qui suit résulte d'expériences visant à construire un système de macros
pour un générateur de code "assez bête" par empilage de structures
stéréotypées... Donc ceci n'est pas à considérer comme un apprentissage
humain...

Le but serait d'obtenir quelque chose ressemblant à ça:

BLOC
{
code normal;
BLOC
{
/* ici code interdit; */
ENTETE( arguments)
code normal;
}
code normal;
}

et satisfaisant les contraintes suivantes :
- il est possible de ne pas avoir d'ENTETE() dans un BLOC, que du code
normal
- s'il y en a un, alors il doit se trouver au tout début du BLOC
- il ne peut pas y avoir d'autre ENTETE() dans le même BLOC, la création
d'un BLOC imbriqué est obligatoire
- ENTETE() peut produire un break; et donc BLOC doit avoir une syntaxe selon
laquelle ce break; fait sortir du BLOC
- BLOC n'est pas une boucle, le code contenu est exécuté une seule fois.

Je souhaite que tout code mal formé produise des erreurs de syntaxe C qui le
rendent incompilable.

Les solutions mises en oeuvre sont les suivantes :

#define BLOC switch( *(( int *) _pE))
où _pE est une variable de type int * existante dans le système

#define ENTETE( arguments) \
default: \
char ForceBloc = 0; \
/* traitement utile */ \
if( _pE != 0) \
break;

En désactivant localement le warning du compilo pour les switch() vides,
toutes les conditions sont remplies, à l'exception de la deuxième, et là je
suis très étonné parce que ça donne :

switch( *(( int *) _pE))
{
/* ici code interdit qui est pourtant accepté */
default:
char ForceBloc = 0;
/* traitement utile */
if( _pE != 0)
break;
code normal ;
}

A part l'initialisation d'une variable déclarée localement, donc un :
char * Test = "zut !"; // => erreur "initialisation skippée par le
default:"
... tout code semble acceptable en entrée du switch, avant le "default:" !!!

Est-ce un bug de mon compilateur (celui de VC6), où existe-t-il une
sémantique qui l'explique ?

Auriez-vous une idée qui puisse prendre place dans ces macros et qui
interdise tout code à cet endroit (sans pour autant imposer la présence d'un
ENTETE() dans un BLOC ?

Il est envisageable si c'est nécessaire que les macros embarquent l'accolade
ouvrante (des macros de fermeture seront alors fournies pour l'homogénéité.

Merci de vos conseils.
Cordialement,

--
/***************************************\
* Patrick BRUNET
* E-mail: lien sur http://zener131.free.fr/ContactMe
\***************************************/

10 réponses

1 2
Avatar
Antoine Leca
En <news:427b6bce$0$964$,
Patrick 'Zener' Brunet va escriure:
Je souhaite que tout code mal formé produise des erreurs de syntaxe C
qui le rendent incompilable.


Cela na va pas être facile. En général ceux qui écrivent les compilateurs
s'ingénient à tout faire pour des codes, mêmes TRÈS tordus au niveau de la
syntaxe, SOIENT compilables. Autrement dit, le contraire.


là je suis très étonné parce que ça donne :

switch( *(( int *) _pE))
{
/* ici code interdit qui est pourtant accepté */


Bin oui! Rien dans la syntaxe du langage C n'interdit d'avoir des
déclarations (utiles) ou des instructions (inutiles car jamais exécutées) au
début d'une instruction bloc enfant d'une instruction switch().

Il y a une raison pour que cela ne change pas dans le folkore; cela
s'appelle le truc à Tom Duff ("Duff's device", détails en anglais à
http://www.lysator.liu.se/c/duffs-device.html, ou
http://groups-beta.google.com/group/net.lang.c/msg/66008138e07aa94c pour
l'original). En gros, ce qui vient derrière la parenthèse fermante du
switch() doit être une instruction (c'est pareil que pour if()), sans
exclusive. Thomas Duff utilisa une instruction do() (qui à son tour possède
un bloc), et a parsemé les étiquettes case un peu partout. Et c'est du C
légal, norme ISO et tout et tout.

Alors quand on en est là, une simple instruction au début du bloc du
switch()... ;-)


Est-ce un bug de mon compilateur (celui de VC6),


Non.


Auriez-vous une idée qui puisse prendre place dans ces macros et qui
interdise tout code à cet endroit (sans pour autant imposer la
présence d'un ENTETE() dans un BLOC ?


Comme cela à froid, non, désolé.


Antoine

Avatar
Harpo
Patrick 'Zener' Brunet wrote:

Bonjour.

Ce qui suit résulte d'expériences visant à construire un système de
macros pour un générateur de code "assez bête" par empilage de
structures stéréotypées... Donc ceci n'est pas à considérer comme un
apprentissage humain...


Je ne connais pas suffisamment ce que vous voulez faire pour donner une
avis interessant. Il y a sans doute d'autres possibilités que
d'utiliser le macro processeur du C pour faire ce que vous voulez, il
existe d'autres macro-processeurs comme m4 , plus puissants, et
beaucoup d'outils pouvant servir à la génération de code.

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

Avatar
Patrick 'Zener' Brunet
Bonjour.

En <news:427b6bce$0$964$,
Patrick 'Zener' Brunet va escriure:
Je souhaite que tout code mal formé produise des erreurs de syntaxe C
qui le rendent incompilable.


Cela na va pas être facile. En général ceux qui écrivent les
compilateurs s'ingénient à tout faire pour des codes, mêmes TRÈS
tordus au niveau de la syntaxe, SOIENT compilables. Autrement dit, le
contraire.



Entendons-nous bien : ce que je veux, c'est que le compilo trouve des
erreurs de syntaxe, et donc en fait je veux créer des extensions dotées de
contraintes fortes.
Si vous avez essayé de compiler mon code, vous avez pu vérifier que les
contraintes spécifiées sont incontournables sans causer une faute de syntaxe
(sauf donc la deuxième).

là je suis très étonné parce que ça donne :

switch( *(( int *) _pE))
{
/* ici code interdit qui est pourtant accepté */


Bin oui! Rien dans la syntaxe du langage C n'interdit d'avoir des
déclarations (utiles) ou des instructions (inutiles car jamais
exécutées) au début d'une instruction bloc enfant d'une instruction
switch().



Ben oui, c'est ce que je craignais : du code mort évident en clair, mais
dangereux lorsque les macros sont utilisées.

Il y a une raison pour que cela ne change pas dans le folkore; cela
s'appelle le truc à Tom Duff ("Duff's device", détails en anglais à
http://www.lysator.liu.se/c/duffs-device.html, ou
http://groups-beta.google.com/group/net.lang.c/msg/66008138e07aa94c
pour l'original). En gros, ce qui vient derrière la parenthèse
fermante du switch() doit être une instruction (c'est pareil que pour
if()), sans exclusive. Thomas Duff utilisa une instruction do() (qui
à son tour possède un bloc), et a parsemé les étiquettes case un peu
partout. Et c'est du C légal, norme ISO et tout et tout.

Alors quand on en est là, une simple instruction au début du bloc du
switch()... ;-)



Hmmmmm :-/ Je suis sceptique (ou est-ce une idée fausse ?)

J'ai regardé les deux exemples de code : je ne cherche même pas à savoir ce
que ça peut faire au juste en dynamique, mais :
- dans le premier on a un do{ } while(); sans les accolades, ce qui
syntaxiquement ne me choque pas (on le fait avec tous les "block openers",
donc pourquoi pas avec un do-while ?),
- et dans le second il y a bien un "case 0:" avant la première instruction
du switch() même si ensuite les autres font des sauts dans la boucle.
Bref prévoir le runtime est assez casse-tête, mais syntaxiquement, le
premier passe sans problème, le second montre un gros laxisme au niveau du
mot-clé "case"...

Dans mon cas, on a je le rappelle :

switch( i)
{
code interdit ici;
default:
code légitime ici;
}

Je ne vois pas du tout ce que le compilo peut espérer faire du code
illégitime sans un label avant : si je devais implémenter un tel switch() je
ne saurais pas où insérer ce code et donc je me sentirais forcé de lever une
erreur de syntaxe !

Est-ce un bug de mon compilateur (celui de VC6),
Non.


Auriez-vous une idée qui puisse prendre place dans ces macros et qui
interdise tout code à cet endroit (sans pour autant imposer la
présence d'un ENTETE() dans un BLOC ?
Comme cela à froid, non, désolé.



Bon, après tout, il me suffira de touver une astuce pour vérifier qu'il n'y
a rien entre un ouvrant de BLOC et un ENTETE(), j'ai validé tout le reste.

Je ne suis pas sûr non plus que tous les compilos acceptent des switch()
sans aucun label dedans, alors je vais revenir à la solution initiale :

#define OUVRE_BLOC switch( ((int) _pE) & 0) { default:
où _pE est une variable de type int * existante dans le système

#define FERME_BLOC }

#define ENTETE( arguments)
char ImposeBloc = 0;
/* traitement utile */
if( _pE != 0)
break;

Et donc l'utilisation est :

/* erreur de syntaxe si on active car hors de tout BLOC */
/* ENTETE( arguments) */

OUVRE_BLOC
{ ce code ici doit fonctionner; }
OUVRE_BLOC
/* ici pas de code, vérification visuelle */
ENTETE( arguments)
{ ce code ici doit fonctionner; }

/* erreur de syntaxe si on active celui-là : "ImposeBloc" */
/* ENTETE( arguments) */

/* Il faut un BLOC imbriqué comme ça :*/
OUVRE_BLOC
/* ici pas de code, vérification visuelle */
ENTETE( arguments)
{ ce code ici doit fonctionner; }
FERME_BLOC

FERME_BLOC
{ ce code ici doit fonctionner; }
FERME_BLOC

Est-ce qu'à l'occasion quelqu'un pourrait me dire si ce code pose des
problèmes de compilation sur divers compilateurs C "décents ou
incontournables" (des mondes Linux, Mac, ou plates-formes moins répandues) ?
(normalement il y aura simplement des warnings "switch sans case" et un
pragma disponible pour les désactiver)

Merci beaucoup...

Pour la peine, je vous dis à quoi ça sert ... C'est assez simple :
Si dans la macro ENTETE() vous imaginez que le "traitement utile" est
spécifié par les arguments de la macro, et que c'est lui qui assigne la
variable _pE, vous arrivez à un fonctionnement global équivalent à un
mécanisme de propagation d'exceptions... Bien sûr, j'ai une bonne raison de
vouloir faire ça ainsi en C pur...

Cordialement,

--
/***************************************
* Patrick BRUNET
* E-mail: lien sur http://zener131.free.fr/ContactMe
***************************************/


Avatar
Antoine Leca
En <news:427ba6b8$0$318$,
Patrick 'Zener' Brunet va escriure:
En <news:427b6bce$0$964$,
Patrick 'Zener' Brunet va escriure:
Je souhaite que tout code mal formé produise des erreurs de syntaxe
C qui le rendent incompilable.


Cela na va pas être facile. En général ceux qui écrivent les
compilateurs s'ingénient à tout faire pour des codes, mêmes TRÈS
tordus au niveau de la syntaxe, SOIENT compilables. Autrement dit, le
contraire.



Entendons-nous bien : ce que je veux, c'est que le compilo trouve des
erreurs de syntaxe, et donc en fait je veux créer des extensions
dotées de contraintes fortes.


J'avais bien entendu. Et je me répète: en général, les compilateurs
cherchent à créer des extensions dans les trous de la syntaxe. Mais là, la
syntaxe est PERMISE dès le départ, donc je vois mal les compilateurs en
train de l'interdire.


Hmmmmm :-/ Je suis sceptique (ou est-ce une idée fausse ?)

J'ai regardé les deux exemples de code :


Pardon, je ne comprend plus. Quels deux exemples?


Dans mon cas, on a je le rappelle :

switch( i)
{
code interdit ici;
default:
code légitime ici;
}

Je ne vois pas du tout ce que le compilo peut espérer faire du code
illégitime sans un label avant : si je devais implémenter un tel
switch() je ne saurais pas où insérer ce code et donc je me sentirais
forcé de lever une erreur de syntaxe !


Quand il existe une norme pour un langage, cela n'appartient plus à celui
qui écrit le compilateur de déterminer s'il faut lever une erreur de syntaxe
ou pas: cette responsabilité a été transférée à celui qui définit la norme.
Tout au plus l'implémenteur peut décider d'émettre ou pas des avertissements
pour les constructions « curieuses ». Mais si la norme décide que de telles
constructions doivent être acceptées, elles doivent l'être, force doit
rester à la loi.


Et en écrivant cela, je suis parfaitement conscient que l'on peut trouver
des compilateurs qui dans certains modes forcent TOUS les avertissements à
être des erreurs de compilation; et ensuite des standards de programmation
qui instaure ce mode, prévu initialement comme une aide au développement, à
être la norme pour TOUS les programmes, ce qui peut amener à avoir des
résultats baroques.


Bon, après tout, il me suffira de touver une astuce pour vérifier
qu'il n'y a rien entre un ouvrant de BLOC et un ENTETE(), j'ai validé
tout le reste.


Par exemple, tu laisses une construction (déclaration ou instruction)
ouverte, c'est-à-dire sans le point-virgule dans BLOC; et tu la fermes dans
ENTETE. Comme cela, si on te rajoute quelque chose au milieu, cela va
générer des erreurs de syntaxes (incompréhensibles, mais là c'est un autre
problème).

Un exemple de telle déclaration pourrait être

struct MonMachinÀMOI { int je_ne_sert_à_rien

/* là il ne doit rien y avoir */

; } ;

Si j'étais toi, je rajouterais aussi moult commentaires, par exemple pour
comprendre ce que j'ai fait quand je me relirai en 2006 (l'année peut être
différente pour toi).



Je ne suis pas sûr non plus que tous les compilos acceptent des
switch() sans aucun label dedans,


Pourtant, ce serait légal, à défaut d'être intelligent.
C'est juste une manière compliquée d'écrire

if(0) {



}


Antoine



Avatar
Laurent Deniau
Patrick 'Zener' Brunet wrote:
Bonjour.

Ce qui suit résulte d'expériences visant à construire un système de macros
pour un générateur de code "assez bête" par empilage de structures
stéréotypées... Donc ceci n'est pas à considérer comme un apprentissage
humain...

Le but serait d'obtenir quelque chose ressemblant à ça:

BLOC
{
code normal;
BLOC
{
/* ici code interdit; */
ENTETE( arguments)
code normal;
}
code normal;
}

et satisfaisant les contraintes suivantes :
- il est possible de ne pas avoir d'ENTETE() dans un BLOC, que du code
normal
- s'il y en a un, alors il doit se trouver au tout début du BLOC
- il ne peut pas y avoir d'autre ENTETE() dans le même BLOC, la création
d'un BLOC imbriqué est obligatoire
- ENTETE() peut produire un break; et donc BLOC doit avoir une syntaxe selon
laquelle ce break; fait sortir du BLOC
- BLOC n'est pas une boucle, le code contenu est exécuté une seule fois.

Je souhaite que tout code mal formé produise des erreurs de syntaxe C qui le
rendent incompilable.

Les solutions mises en oeuvre sont les suivantes :

#define BLOC switch( *(( int *) _pE))
où _pE est une variable de type int * existante dans le système

#define ENTETE( arguments)
default:
char ForceBloc = 0;
/* traitement utile */
if( _pE != 0)
break;

En désactivant localement le warning du compilo pour les switch() vides,
toutes les conditions sont remplies, à l'exception de la deuxième, et là je
suis très étonné parce que ça donne :

switch( *(( int *) _pE))
{
/* ici code interdit qui est pourtant accepté */
default:
char ForceBloc = 0;
/* traitement utile */
if( _pE != 0)
break;
code normal ;
}

A part l'initialisation d'une variable déclarée localement, donc un :
char * Test = "zut !"; // => erreur "initialisation skippée par le
default:"
... tout code semble acceptable en entrée du switch, avant le "default:" !!!

Est-ce un bug de mon compilateur (celui de VC6), où existe-t-il une
sémantique qui l'explique ?

Auriez-vous une idée qui puisse prendre place dans ces macros et qui
interdise tout code à cet endroit (sans pour autant imposer la présence d'un
ENTETE() dans un BLOC ?


#define CAT(a,b) CAT_
#define CAT_(a,b) a ## b

#define ENTETE( arguments)
int CAT(_,__LINE__) = 0; (void)CAT(_,__LINE__);

default:
char ForceBloc = 0;
/* traitement utile */
if( _pE != 0)
break;


Cela n'empeche pas "tout code" mais empeche du code qui n'est pas du
code d'initialisation.

a+, ld.

Avatar
Patrick 'Zener' Brunet
Bonjour.

En <news:427ba6b8$0$318$,
Patrick 'Zener' Brunet va escriure:
En <news:427b6bce$0$964$,
Patrick 'Zener' Brunet va escriure:
Je souhaite que tout code mal formé produise des erreurs de syntaxe
C qui le rendent incompilable.


Cela na va pas être facile. En général ceux qui écrivent les
compilateurs s'ingénient à tout faire pour des codes, mêmes TRÈS
tordus au niveau de la syntaxe, SOIENT compilables. Autrement dit,
le contraire.



Entendons-nous bien : ce que je veux, c'est que le compilo trouve des
erreurs de syntaxe, et donc en fait je veux créer des extensions
dotées de contraintes fortes.


J'avais bien entendu. Et je me répète: en général, les compilateurs
cherchent à créer des extensions dans les trous de la syntaxe. Mais
là, la syntaxe est PERMISE dès le départ, donc je vois mal les
compilateurs en train de l'interdire.



OK, on est d'accord sur ce point : vous donnez vous-même plus bas un moyen
de produire une syntaxe inacceptable pour tout compilateur correct. Et moi
je veux en plus que l'erreur produite ait de bonnes chances d'être
compréhensible par rapport à mon contexte (en ayant lu la notice, donc c'est
un pense-bête). C'est pourquoi par exemple je nomme la variable qui la
déclenche "ForceBloc".


Hmmmmm :-/ Je suis sceptique (ou est-ce une idée fausse ?)

J'ai regardé les deux exemples de code :


Pardon, je ne comprend plus. Quels deux exemples?



Donnés dans les pages dont vous avez fourni le lien dans votre première
intervention (et qui se recoupent).


Dans mon cas, on a je le rappelle :

switch( i)
{
code interdit ici;
default:
code légitime ici;
}

Je ne vois pas du tout ce que le compilo peut espérer faire du code
illégitime sans un label avant : si je devais implémenter un tel
switch() je ne saurais pas où insérer ce code et donc je me sentirais
forcé de lever une erreur de syntaxe !


Quand il existe une norme pour un langage, cela n'appartient plus à
celui qui écrit le compilateur de déterminer s'il faut lever une
erreur de syntaxe ou pas: cette responsabilité a été transférée à
celui qui définit la norme. Tout au plus l'implémenteur peut décider
d'émettre ou pas des avertissements pour les constructions «
curieuses ». Mais si la norme décide que de telles constructions
doivent être acceptées, elles doivent l'être, force doit rester à la
loi.



Oui, je veux bien, mais il me semble bien (surtout après l'histoire du if(0)
plus bas) que ce code est équivalent conceptuellement - et au mieux - à
celui-ci :

if( 0)
{
code interdit ici;
}
switch( i)
{
default:
code légitime ici;
}

D'où la question : comment a-t-on pu normaliser ça sans avoir fumé des trucs
bizzares avant ? Avec la volonté de planquer du code mort ? Ca me rappelle
un peu une certaine pseudo-interview de Bjarne Stroustroup :-D


Bon, après tout, il me suffira de touver une astuce pour vérifier
qu'il n'y a rien entre un ouvrant de BLOC et un ENTETE(), j'ai validé
tout le reste.


Par exemple, tu laisses une construction (déclaration ou instruction)
ouverte, c'est-à-dire sans le point-virgule dans BLOC; et tu la
fermes dans ENTETE. Comme cela, si on te rajoute quelque chose au
milieu, cela va générer des erreurs de syntaxes (incompréhensibles,
mais là c'est un autre problème).



Non, ça c'est pas bon parce qu'un BLOC peut aussi ne pas contenir d'ENTETE()
et seulement du code normal.

Je crois vraiment qu'il est impossible de produire une erreur de syntaxe à
cet endroit, par un moyen qui soit compatible avec les cas d'utilisation
prévus.

Si j'étais toi, je rajouterais aussi moult commentaires, par exemple
pour comprendre ce que j'ai fait quand je me relirai en 2006 (l'année
peut être différente pour toi).

Mes toolkits sont toujours dotés d'une notice complète, pas de problème je

suis d'accord !

Je ne suis pas sûr non plus que tous les compilos acceptent des
switch() sans aucun label dedans,


Pourtant, ce serait légal, à défaut d'être intelligent.
C'est juste une manière compliquée d'écrire

if(0) {
}



Exact, si c'est if(0) il faut absolument que je remette le "default:" pour
en faire un if(1) ! Ca doit compiler mais ça doit aussi marcher !!!!

Cordialement,

--
/***************************************
* Patrick BRUNET
* E-mail: lien sur http://zener131.free.fr/ContactMe
***************************************/




Avatar
Patrick 'Zener' Brunet
Bonjour.

Patrick 'Zener' Brunet wrote:
[...]
Auriez-vous une idée qui puisse prendre place dans ces macros et qui
interdise tout code à cet endroit (sans pour autant imposer la
présence d'un ENTETE() dans un BLOC ?


#define CAT(a,b) CAT_
#define CAT_(a,b) a ## b

#define ENTETE( arguments)
int CAT(_,__LINE__) = 0; (void)CAT(_,__LINE__);

default:
char ForceBloc = 0;
/* traitement utile */
if( _pE != 0)
break;


Cela n'empeche pas "tout code" mais empeche du code qui n'est pas du
code d'initialisation.



Initialement (voir mon post du 6 à 19h15), le "default:" faisait partie du
BLOC, et d'ailleurs il y est retourné désormais pour éviter d'autres
problèmes...

Avec le code ci-dessus, j'ai d'emblée une erreur (C2360 sous VC6) disant que
l'initialisation de _666 est sautée par le default case, ceci même sans code
en zone interdite (avant le ENTETE() ).

Effectivement, c'est pour ça que j'avais tenté de descendre le "default:"
dans ENTETE(), pour provoquer de telles erreurs, mais le code suivant
passent sans problème dans la zone interdite :

char * toto;
FunctionXyz( &toto);

Donc en fait ça ne m'arrange pas parce que c'est une fausse sécurité selon
le code, je préfère choisir entre toujours ou jamais d'erreur.

En passant, pourriez-vous me dire pourquoi vous rajoutez l'instruction :

(void) _666;

?

(En pratique, l'utilisation de _LINE_ n'est pas nécessaire du fait qu'il n'y
a qu'un ENTETE() possible dans un BLOC, c'est justement ForceBloc qui
l'impose en ayant un nom qui se répète).

Merci,
Cordialement,

--
/***************************************
* Patrick BRUNET
* E-mail: lien sur http://zener131.free.fr/ContactMe
***************************************/


Avatar
Laurent Deniau
Patrick 'Zener' Brunet wrote:
Bonjour.


Patrick 'Zener' Brunet wrote:

[...]
Auriez-vous une idée qui puisse prendre place dans ces macros et qui
interdise tout code à cet endroit (sans pour autant imposer la
présence d'un ENTETE() dans un BLOC ?


#define CAT(a,b) CAT_



Oups, j'ai ete un peu vite:

#define CAT(a,b) CAT_(a,b)

#define CAT_(a,b) a ## b

#define ENTETE( arguments)
int CAT(_,__LINE__) = 0; (void)CAT(_,__LINE__);

default:
char ForceBloc = 0;
/* traitement utile */
if( _pE != 0)
break;


Cela n'empeche pas "tout code" mais empeche du code qui n'est pas du
code d'initialisation.




Initialement (voir mon post du 6 à 19h15), le "default:" faisait partie du
BLOC, et d'ailleurs il y est retourné désormais pour éviter d'autres
problèmes...

Avec le code ci-dessus, j'ai d'emblée une erreur (C2360 sous VC6) disant que
l'initialisation de _666 est sautée par le default case, ceci même sans code
en zone interdite (avant le ENTETE() ).

Effectivement, c'est pour ça que j'avais tenté de descendre le "default:"
dans ENTETE(), pour provoquer de telles erreurs, mais le code suivant
passent sans problème dans la zone interdite :

char * toto;
FunctionXyz( &toto);


Tu dois etre en C99. Autant pour moi, j'ai une fois de plus reflechis en
C89.

Donc en fait ça ne m'arrange pas parce que c'est une fausse sécurité selon
le code, je préfère choisir entre toujours ou jamais d'erreur.

En passant, pourriez-vous me dire pourquoi vous rajoutez l'instruction :

(void) _666;


Pour eviter un warning "variable _666 not used"

(En pratique, l'utilisation de _LINE_ n'est pas nécessaire du fait qu'il n'y
a qu'un ENTETE() possible dans un BLOC, c'est justement ForceBloc qui
l'impose en ayant un nom qui se répète).


Quel identifieur tu utiliserais pour garantir l'unicite de ton identifieur?

a+, ld.



Avatar
Harpo
Laurent Deniau wrote:

En passant, pourriez-vous me dire pourquoi vous rajoutez
l'instruction :

(void) _666;


Pour eviter un warning "variable _666 not used"


C'est une solution diabolique !

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


Avatar
Patrick 'Zener' Brunet
Bonjour.

Patrick 'Zener' Brunet wrote:
Patrick 'Zener' Brunet wrote:
[...]
Auriez-vous une idée qui puisse prendre place dans ces macros et
qui interdise tout code à cet endroit (sans pour autant imposer la
présence d'un ENTETE() dans un BLOC ?


#define CAT(a,b) CAT_



Oups, j'ai ete un peu vite:


Oui, je connais bien le PPC !
Alors je les ai entérinés définitivement dans un header qui regroupe tous
ces machins qu'on passe son temps à réécrire !

[...]
(En pratique, l'utilisation de _LINE_ n'est pas nécessaire du fait
qu'il n'y a qu'un ENTETE() possible dans un BLOC, c'est justement
ForceBloc qui l'impose en ayant un nom qui se répète).


Quel identifieur tu utiliserais pour garantir l'unicite de ton
identifieur?

Il n'y a que _LINE_ qui le permette (sauf manque de chance avec plusieurs

fichiers inclus à la file), et ça ne permet d'en construire qu'une série
unique par invocation de la macro.
C'est selon moi un gros manque du préprocesseur : je rêve d'une simple macro
qui produise un nombre auto-incrémentable...

Il m'est d'ailleurs arrivé à une époque d'utiliser une première passe du
préprocesseur seul (avant la compilation complète) pour faire un
pré-traitement sur le fichier. Là on peut générer des commentaires, des
#define, etc.

Par rapport à un autre préprocesseur (M4 par exemple), l'avantage du PPC est
d'être toujous inclus et configuré ad-hoc dans la chaîne de compilation dont
on dispose.

Cordialement,

--
/***************************************
* Patrick BRUNET
* E-mail: lien sur http://zener131.free.fr/ContactMe
***************************************/




1 2