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

Suite: Aux experts du préprocesseur + 1 question

13 réponses
Avatar
ludovicd
Bonjour,

J'aimerai savoir si il exite une directive qui permet au
pr=E9processeur de pr=E9traiter un fichier deux fois plut=F4t qu'une avant
compilation. Et ce pour que le code suivant est un sens (qui ne
fonctionnerai, selon ma compr=E9hension, qu'au deuxi=E8me pr=E9traitement)


#define D define

#define foo(x,y) foo_2arg(x,y+NULL)

# D MACONST 0xfff
# D foo_2arg(x,y) foo_2arg_prime( x ## * MACONST, y)

int fct(int * a)
{
return foo(22, a)
}


Dans le cas ou une telle directive n'existe pas, est-ce que il existe
une mani=E8re standard ou =E0 d=E9faut, disponible sur tous les
compilateurs, de r=E9clamer une telle op=E9ration dans ses fichiers de
configuration?

Une question:


En C++, il existe deux fonctionnalit=E9s tr=E8s int=E9ressantes, soit la
surcharge d'op=E9rateurs et de fonctions. Est-ce que ces
fonctionnalit=E9s pourraient =EAtre mim=E9s en C?



Merci pour vos r=E9ponses,


Ludovic Darmk,

10 réponses

1 2
Avatar
Radamanthe
wrote:
Bonjour,

J'aimerai savoir si il exite une directive qui permet au
préprocesseur de prétraiter un fichier deux fois plutôt qu'une avant
compilation.


De manière standard, non.

Et ce pour que le code suivant est un sens (qui ne
fonctionnerai, selon ma compréhension, qu'au deuxième prétraitement)


#define D define

#define foo(x,y) foo_2arg(x,y+NULL)


Pourquoi +NULL ?

# D MACONST 0xfff
# D foo_2arg(x,y) foo_2arg_prime( x ## * MACONST, y)

int fct(int * a)
{
return foo(22, a)
}


Ce charabia n'est pas du C. Il faudrait autre chose que des passes de
preprocessing (au sens C) pour que ça daigne un jour se compiler. Qui
enlevera l'espace entre # et D ? Sans doute pas le prepro. De toutes
façons, il fera dans sa culotte à la première passe.

Dans le cas ou une telle directive n'existe pas, est-ce que il existe
une manière standard ou à défaut, disponible sur tous les
compilateurs, de réclamer une telle opération dans ses fichiers de
configuration?


Rien n'empêche à priori d'envoyer manuellement le fichier source vers le
préprocesseur (en principe, c'est un programme séparé appelé par le
compilo) et de diriger la sortie vers le compilo (qui refera une passe
en appelant le prepro). On peut aussi passer par un fichier
intermédiaire (risque d'être très gros pour un simple include). Mais
rien de ceci n'est standard, à savoir qu'il faudra procéder de manière
différente d'une implémentation à l'autre, sans même être sûr que c'est
toujours praticable. Pratiquement, qu'on fasse du portable ou non, c'est
rechercher les ennuis.

J'avoue ne jamais avoir eu à me plier à ce genre d'exercice. D'ailleurs,
je ne suis pas sûr que ça fonctionne sans compliquer encore plus la
gestion des effets de bords inhérants au préprocesseur... alors après
s'il faut dépiauter le bidule qui déconne, autant tout refaire.

Bon de toutes façons, pour ton exemple, c'est coton. T'en as d'autres ?


Une question:


En C++, il existe deux fonctionnalités très intéressantes, soit la
surcharge d'opérateurs et de fonctions. Est-ce que ces
fonctionnalités pourraient être mimés en C?


Non. Ca serait bien hein ?


--
R.N.

Avatar
ludovicd

Ce charabia n'est pas du C. Il faudrait autre chose que des passes de
preprocessing (au sens C) pour que ça daigne un jour se compiler. Qui
enlevera l'espace entre # et D ? Sans doute pas le prepro. De toutes
façons, il fera dans sa culotte à la première passe.


L'espace entre le # et D est heureusement permis dans le C standard.

Ludovic
Darmk

Avatar
Radamanthe
wrote:

Ce charabia n'est pas du C. Il faudrait autre chose que des passes de
preprocessing (au sens C) pour que ça daigne un jour se compiler. Qui
enlevera l'espace entre # et D ? Sans doute pas le prepro. De toutes
façons, il fera dans sa culotte à la première passe.


L'espace entre le # et D est heureusement permis dans le C standard.


En effet, mea culpa :) Mais je ne comprendre pas le but de la manoeuvre
dans l'exemple ? Par quoi d'autre penses-tu le remplacer ?



--
R.N.


Avatar
Antoine Leca
Je ne suis pas expert du préprocesseur, en fait je n'y connais presque rien,
mais je peux essayer de répondre à tes questions, cela te permettra
peut-être d'avancer.


écrivit dans
news::
J'aimerai savoir si il exite une directive qui permet au
préprocesseur de prétraiter un fichier deux fois plutôt qu'une avant
compilation.


Normalement non.


Et ce pour que le code suivant est un sens (qui ne
fonctionnerai, selon ma compréhension, qu'au deuxième prétraitement)


Pas d'accord.


#define D define

#define foo(x,y) foo_2arg(x,y+NULL)

# D MACONST 0xfff


À la première passe, cela va être refusé tout net (la directive "D" n'existe
pas en C).
Si tu veux jouer au plus malin, tu peux essayer des trucs comme

?
?= D MACONST 0xfff

mais c'est parfaitement affreux, ÀMHA.


# D foo_2arg(x,y) foo_2arg_prime( x ## * MACONST, y)


Officiellement, x##* (à la deuxième passe) ne peut pas fonctionner,
puisqu'aucun opérateur du C (aucun lexème) n'est formé de 2+ caractères
terminant par *, donc l'opérateur ## ne réussira pas à créer un nouveau
lexème _valide_ (sauf des versions TRÈS anciennes, qui accepteraient encore
l'opérateur =*).

Dans la pratique, cela va la plupart du temps fonctionner.
Mais je ne vois aucun intérêt à mettre un ## ici.


int fct(int * a)
{
return foo(22, a)
}


Euh, peux-tu expliquer ce que tu veux obtenir (éventuellement en détaillant
chacune des deux « phases ») ?

Si tu veux arriver à

int fct(int*a){return foo_2arg_prime(22*0xfff,a+NULL)}

(avec une erreur de compilation à la clé avant le dernier lexème), je ne
vois pas l'intérêt de cette complexité : tu mets define à la place D, et
cela marche tout seul.

Si tu veux arriver à autre chose, merci d'expliciter.


Dans le cas ou une telle directive n'existe pas, est-ce que il existe
une manière standard


Appeler $(CPP) ou /bin/cpp (dans le Makefile ou éqv.)


ou à défaut, disponible sur tous les compilateurs,


Absolument impossible et irréaliste : un grand nombre de compilateurs à
l'heure actuelle n'ont même plus de préprocesseurs séparés !
Architecturellement, la distinction avait une certaine logique à l'époque de
V7, c'est-à-dire vers 1978. Mais c'était il y a 30 ans ! (pour un langage
qui en a 35).
Aujourd'hui, cette histoire du préprocesseur de macros séparé est un acquis
historique du langage C que l'on ne peut plus effacer et qu'il faut subir en
silence ; mais vouloir jouer à des subtilités avec relève de l'amusement,
pas de la portabilité « sur tous les compilateurs ».


Une question: En C++,


fr.comp.lang.c++


Antoine

Avatar
Antoine Leca
Harpo écrivit dans news:45b65fa3$0$31459$:
Si tu utilises GCC :
man cpp


Hum...

C>gcc -v
Reading specs from bin/../lib/gcc/mingw32/3.4.2/specs
Configured with: ../gcc/configure --with-gcc --with-gnu-ld
--with-gnu-as --host=mingw32 --target=mingw32 --prefix=/mingw
--enable-threads --disable-nls
--enable-languages=c,c++,f77,ada,objc,java
--disable-win32-registry --disable-shared
--enable-sjlj-exceptions --enable-libgcj --disable-java-awt
--without-x --enable-java-gc=boehm --disable-libgcj-debug
--enable-interpreter --enable-hash-synchronization
--enable-libstdcxx-debug
Thread model: win32
gcc version 3.4.2 (mingw-special)

C>man cpp
"man" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.


Antoine

Avatar
ludovicd
On 24 jan, 09:53, "Antoine Leca" wrote:


J'aimerai savoir si il exite une directive qui permet au
préprocesseur de prétraiter un fichier deux fois plutôt qu'une av ant
compilation.Normalement non.



J'ai en effet cherché dans la man de gcc et même si il y a des
options assez cryptiques (même certaines qui utilise uniquement les
macros d'un header et pas les déclaration et d'autres dont l'usage est
"découragé"!) il ne semble pas avoir à priori de moyen de
prétraiter deux fois. Je vais continuer mes recherches...


Et ce pour que le code suivant est un sens (qui ne
fonctionnerai, selon ma compréhension, qu'au deuxième prétraiteme nt)Pas d'accord.



Si on peut prétraiter récursivement, on peut faire a peu près
n'importe quoi en autant que l'exécution du programme contrôlant le
préprocesseur se termine complêtement, écrit au fichier, puis
redémarre. Tel que vu, dans les concours de l'IOCCC, ça fonctionne
bien. Maintenant désolé de devoir saluer un tel standard.



#define D define

#define foo(x,y) foo_2arg(x,y+NULL)

# D MACONST 0xfffÀ la première passe, cela va être refusé tout net (la directive "D" n'existe
pas en C).

Si tu veux jouer au plus malin, tu peux essayer des trucs comme

?
?= D MACONST 0xfff

mais c'est parfaitement affreux, ÀMHA.


Encore une fois, tel que vu dans les concours de l'IOCCC, # D sera
ignoré par le préprocesseur silencieusement (puisque ce n'est pas une
directive, jusqu'à ce que D soit remplacé par define, dans un
deuxième prétraitement, qui aura lieu dans une deuxième exécution
du préprocesseur...)


(avec une erreur de compilation à la clé avant le dernier lexème), je ne
vois pas l'intérêt de cette complexité : tu mets define à la plac e D, et
cela marche tout seul.

Si tu veux arriver à autre chose, merci d'expliciter.


En pouvant utiliser un outils standard reconnu comme le
préprocesseur, (même si cela devait conduire à spécifier des
paramètres particuliers à chaque environnement de dévellopement) on
pourrait écrire une/des entêtes qui émule la surcharge d'opérateurs
ou de fonctions en C par exemple... (de façon transparente à
l'utilisateur)


ou à défaut, disponible sur tous les compilateurs,Absolument imposs ible et irréaliste : un grand nombre de compilateurs à
l'heure actuelle n'ont même plus de préprocesseurs séparés !

Architecturellement, la distinction avait une certaine logique à l'ép oque de
V7, c'est-à-dire vers 1978. Mais c'était il y a 30 ans ! (pour un lan gage
qui en a 35).
Aujourd'hui, cette histoire du préprocesseur de macros séparé est u n acquis
historique du langage C que l'on ne peut plus effacer et qu'il faut subir en
silence ; mais vouloir jouer à des subtilités avec relève de l'amus ement,
pas de la portabilité « sur tous les compilateurs ».


Ça me semble à mon grand dam, exact. Je vais poursuivre mes
recherches.



Ludovic


Avatar
ludovicd
Faire référence au concours de l'IOCCC est vraiment manqué de
classe tout compte fait, donc je préfère citer cet exemple de "How
to Write Bug-Free C code"

http://www.duckware.com/bugfreec/chapter2.html

--------------------
2.2.9 Preprocessor Commands Containing Preprocessor Commands

Have you ever wanted to write a macro that referred to another
preprocessing directive? Consider the following example.

Optimize On/Off macros, which do not work
#define OPTIMIZEOFF #pragma optimize("",off)
#define OPTIMIZEON #pragma optimize("",on)



The OPTIMIZEOFF and OPTIMIZEON macros attempt to abstract out how
optimizations are turned off and turned on during a compilation. The
problem with these macros is that they are trying to perform another
preprocessor directive, which is impossible with any standard C
preprocessor. However, this does not mean that it cannot be done.

The solution to this problem is to run the source through the
preprocessor twice during the compile instead of just once. Most
compilers allow you to run only the preprocessing pass of their
compiler and redirect the output to a file. If this output file is then
run back through the compiler, the optimize macros work!

Testing extra preprocessor pass in Microsoft C8 for C code
cl -P test.c
cl -Tctest.i

Testing extra preprocessor pass in Microsoft C8 for C++ code
cl -P test.cpp
cl -Tptest.i
-----------------

Ludovic
Avatar
Antoine Leca
écrivit dans
news::
http://www.duckware.com/bugfreec/chapter2.html

--------------------
2.2.9 Preprocessor Commands Containing Preprocessor Commands

Have you ever wanted to write a macro that referred to another
preprocessing directive? Consider the following example.

Optimize On/Off macros, which do not work
#define OPTIMIZEOFF #pragma optimize("",off)
#define OPTIMIZEON #pragma optimize("",on)


Utiliser _Pragma(). A été rajouté exprès pour cela dans C99 (et bien avant
dans les compilos SGI, entre autres).


Antoine

Avatar
Antoine Leca
écrivit dans
news::
On 24 jan, 09:53, "Antoine Leca" wrote:

Et ce pour que le code suivant est un sens (qui ne
fonctionnerai, selon ma compréhension, qu'au deuxième
prétraitement)
Pas d'accord.



Si on peut prétraiter récursivement, on peut faire a peu près
n'importe quoi en autant que l'exécution du programme contrôlant le
préprocesseur se termine complêtement, écrit au fichier, puis
redémarre. Tel que vu, dans les concours de l'IOCCC, ça fonctionne
bien.


L'IOCCC est tout sauf une référence. De plus, dans les concours de l'IOCCC,
il est explicitement interdit de faire passer deux fois le préprocesseur.

Après, effectivement avec une machine de Turing on peut faire tourner
n'importe quel algorithme. Cela ne veut pas dire que tous les algorithmes
doivent être utilisés.

Ah, et comme je l'écrivais le semaine dernière, plutôt qu'utiliser cpp qui
est somme toute limité et étrange à l'utilisation, on peut aussi
"prétraiter" le source par (liste non limitative): m4, sed/awk, Perl/Python,
voire make (j'ai donné) ou MASM (j'ai donné aussi). Etc.

Ou Cfront, ou gnat...


Maintenant désolé de devoir saluer un tel standard.


Gué ? Queveudir ?


#define D define
# D MACONST 0xfff
À la première passe, cela va être refusé tout net

(la directive "D" n'existe pas en C).


Encore une fois, tel que vu dans les concours de l'IOCCC, # D sera
ignoré par le préprocesseur


C99 seulement (D est alors une «/non-directive/»); et encore, cela me paraît
une erreur de la norme (mais j'ai la flemme de chercher cette petite bête).

Non conforme à C90, ÀMHA (violation d'une contrainte, en l'occurence une
partie "Syntax", diagnostic requis).


[...] silencieusement


:-D
Évidemment, si tu compiles en mode /Silent /Quiet /RebootAfterInstall^W
(genre les programmes d'install de M$), ce sera silencieux... Maintenant,
avec les compilos C, la plupart des gens utilisent plutôt -AAA ou -W4
ou -Wall, autrement dit génération d'un max de commentaires (la plupart
inutiles), et cela m'étonnerait fort que ton truc passe « silencieusement ».
(MDR)


Si tu veux arriver à autre chose, merci d'expliciter.


En pouvant utiliser un outils standard reconnu comme le
préprocesseur, (même si cela devait conduire à spécifier des
paramètres particuliers à chaque environnement de dévellopement) on
pourrait écrire une/des entêtes qui émule la surcharge d'opérateurs
ou de fonctions en C par exemple... (de façon transparente à
l'utilisateur)


Toujours pas compris. Merci de fournir un exemple un tant soit peu réaliste
(pas comme le précédent, où il n'y avait aucun besoin d'utiliser deux
passes).



Antoine



Avatar
Harpo
Antoine Leca wrote:

C>man cpp
"man" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.


Amha, c'est pas une question de locales mais d'OS.

1 2