2010-09-08 3 views
1

Si j'utilise la macro:Est-ce une macro valide dans C?

#define AND 

de la manière suivante:

if(...) 
{ 
... 
} 
elseANDif(...) 
{ 
... 
} 

Quelle sortie ne la produisent préprocesseur?

Edit: Je compte utiliser:

#define TEST(params) if(...){...}else 

le ... si (...) est une expression compliquée en utilisant params

le ... en {...} exécute certaines opérations & est indépendante des paramètres

#define AND 

TEST(x1) AND TEST(x2) 
{ 
    //the code for the final else 
} 
#define AND 

TEST(x1) AND TEST(x2) 
{ 
    //the code for the final else 
} 

Est-ce que l'ET aide ici ou est-ce que je peux m'en passer?

+1

Votre usage prévu est illisible. Si quoi que ce soit, un lecteur s'attendrait à ce que le bloc '// le code du dernier else 'soit exécuté si' a == b && b == c', mais ceci est complètement différent de ce que ferait réellement votre code. Sauf si vous essayez de concevoir une entrée IOCCC, ne le faites pas. – jamesdlin

+0

Il y a beaucoup mieux (comme dans des manières plus lisibles et moins sujette aux erreurs) de faire ce que vous essayez de faire. – bta

Répondre

9

Non, cela ne fonctionnera pas comme prévu. Et vous pouvez tester ce que fait le préprocesseur en exécutant votre code via cpp.

[email protected]:~/temp$ cat z.c 
#define AND 

if(...) 
{ 
    ... 
} 
elseANDif(...) 
{ 
    ... 
} 

[email protected]:~/temp$ cpp z.c 
# 1 "z.c" 
# 1 "<built-in>" 
# 1 "<command-line>" 
# 1 "z.c" 


if(...) 
{ 
    ... 
} 
elseANDif(...) 
{ 
    ... 
} 

Le technique raison est que lorsque cpp macros développe, il recherche un correspondant jeton d'identification complet du nom de cette macro. C'est à dire. dans votre cas, il recherche l'identifiant AND. Cependant, quand il analyse le code, il ne trouve pas un tel identifiant. Il trouve elseANDif ce qui est un identifiant assez différent. Il n'a aucun moyen de diviser elseANDif en constituants, et c'est une bonne chose car sinon les macros fonctionneraient très mal. Imaginez:

const int FUSIONDEBUG = 5; 

Quoi que cela signifie, dans le code C réel cela casserait terriblement, car NDEBUG est presque toujours défini dans le code de production à vide (Google sur ce NDEBUG moyens).


En ce qui concerne votre édition, le meilleur conseil que je peux vous donner sur ces questions est NE PAS FAIRE. (ab) L'utilisation de macros comme celle-ci peut sembler rendre le code plus lisible, mais à long terme, il est moins lisible, avec le danger supplémentaire que les macros soient difficiles à obtenir et que certaines combinaisons de jetons puissent exploser sur vous mal.

Donc, vous pouvez certainement faire sans le AND ainsi que sans le TEST tout à fait.

+0

J'ai un morceau de code qui vérifie si un fichier a été ouvert avec succès ou non, sur la base de laquelle il imprime le message d'erreur ou se déplace sur le fichier-io réel dans la partie else. Parfois, 2 fichiers doivent être ouverts, d'où j'ai ajouté un autre à la macro précédente. Toutes les suggestions que vous pouvez fournir pour faire fonctionner cette macro seraient appréciées. –

+0

@crypto: Je serai ravi de vous aider, mais votre commentaire n'est toujours pas clair pour moi. Puisqu'il s'agit d'un problème tout à fait différent, je vous suggère d'ouvrir une question distincte sur le SO avec un nom approprié et une description détaillée de vos besoins dans le corps de la question. –

+0

Le conseil d'Eli est bon. Bien qu'il soit séduisant d'utiliser des macros pour régler le langage C, c'est un chemin vers la folie. Ne fais pas ça. D'un autre côté, il peut parfois être judicieux d'utiliser des macros en remplacement de fonctions en ligne. – RBerteig

2

Ce:

#define TEST(condn) if(...){...}else 

est un non-sens; Qu'attendez-vous des ellipses (...) à faire!?

l'exemple d'utilisation que vous avez donné élargirait à

if(...){...} else if(...){...}else 
{ 
    //the code for the final else 
} 

qui est un non-sens manifestement; où est l'argument condn utilisé?.De toute façon, quoi que vous vouliez vraiment l'ET n'a aucun effet autre que la lisibilité fictive. Si vous essayez d'inventer un nouveau langage, le préprocesseur C n'est pas le moyen de le faire. Je ne vois aucun avantage par rapport à ce que vous semblez vouloir accomplir par rapport à un code plus simple.

Si vous aviez l'intention:

#define TEST(condn) if(condn){/*some code*/}else 

alors comment est la résultante:

if(a==b){/*some code*/} else if(b==c){/*some code*/}else 
{ 
    //the code for the final else 
} 

mieux que:

if(a==b || b==c) 
{ 
    /*some code*/ 
} 
else 
{ 
    //the code for the final else 
} 

/*some code*/ est inutilement dupliqués?

Notez que ici la seule condition enchaînée par || est équivalente à vos multiples conditions enchaînées par else if, même si vous utilisez la TEST macro, il n'y a pas besoin de l'utiliser de cette façon quand:

TEST(a==b || b==c) 
{ 
    //the code for the final else 
} 

suffira.

Les macros sont souvent mal avisées dans le meilleur des cas, mais vous avez choisi un exemple particulièrement frappant d'abus de macro! Considérons par exemple comment vous pourriez déboguer un tel code dans un débogueur au niveau source.

+0

Je suis d'accord avec vous, mais croyez-vous honnêtement que j'ai des points de suspension (...) dans mon code if? –

+0

S'il vous plaît lire la modification maintenant, je l'ai modifié pour décrire correctement ce que je fais. –

+0

@crypto: Bien sûr que non, mais pourquoi l'afficher de cette façon? Cela crée une ambiguïté inutilement. Cela peut aussi avoir été une tentative incorrecte d'une macro variée. L'édition n'aide pas à clarifier beaucoup. Si vous ne pouvez pas montrer ce que vous faites, il est inutile de le publier du tout. – Clifford

1

La réponse courte à votre question est "oui". Vous pouvez certainement faire ce que vous suggérez. Voici une base, par exemple de travail:

#include <stdio.h> 

#define AND 
#define TEST(params) if (!params) { printf(#params " was false\n"); } else 

int main(int argc, char ** argv) 
{ 
    int param_1 = 1; 
    int param_2 = 0; 

    TEST(param_1) AND TEST(param_2) 
    { 
     printf("success!\n"); 
    } 
} 

Après l'expansion macro, le code ressemblerait essentiellement comme ceci:

int main(int argc, char ** argv) 
{ 
    int param_1 = 1; 
    int param_2 = 0; 

    if (!param_1) { printf("param_1 was false\n"); } else 
    if (!param_2) { printf("param_2 was false\n"); } else 
    { 
     printf("success!\n"); 
    } 
} 

Comme l'a fait par d'autres, faire quelque chose comme cela est discutable parce qu'elle salit avec la façon dont les gens lisent le code et peuvent rendre le débogage ultérieur difficile. Dans un cas comme celui-ci, je recommanderais certainement d'utiliser un appel de fonction si possible. C'est l'approche que Secure recommande dans son commentaire:

int test_parameters(int params) 
{ 
    if (!params) { printf("bad parameters"); return 0; } 
    else { return 1; } 
} 

int main(int argc, char ** argv) 
{ 
    int param_1 = 1; 
    int param_2 = 0; 

    if (test_parameters(param_1) && test_parameters(param_2)) 
    { 
     printf("success!\n"); 
    } 
}