6
votes

C Programmation #define?

Dupliqué possible:
pourrait-on expliquer ces comportements non définis (i = i ++ + ++ i, i = i ++, etc ...) xxx

Je sais quelle est la sortie du code.

as #define travail dans un autre programme De cette façon, cela ne fonctionne pas dans le code ci-dessus Pourquoi?


3 commentaires

Que se passe-t-il lorsque vous compilez et exécutez cela? Les erreurs? Des résultats étranges? Quoi?


Quelle est la sortie que vous attendez et qu'est-ce que vous obtenez? Je suis à peu près sûr que dans x ++ * x ++ et ++ y * ++ y * * Il est indéfini si le premier incrément est arrivé au moment où le second est évalué, la valeur que vous obtenez variera d'un environnement à l'environnement.


Dans votre question originale, il y avait un typo ( #deifne au lieu de #define ) J'ai corrigé maintenant, assurez-vous que le code que vous utilisez est correct.


9 Réponses :


16
votes

Le résultat d'une expression avec plus d'un opérateur ++ sur la même variable est officiellement un comportement indéfini en c.


4 commentaires

Est-ce techniquement "comportement non défini"? Je pensais que c'était un «comportement non spécifié», qui est toujours mauvais, mais limite la mise en œuvre à certains choix (dans ce cas, n'incluez pas de crash).


Oui, c'est certainement indéfini;).


Au fait, cette réponse n'est pas exactement correcte. Une expression peut modifier la même variable plusieurs fois - le comportement n'est indéfini que si entre ces modifications Il n'y a pas de point de séquence (I.e. &&, ||, ?:, Opérateur de virgule ou appel de la fonction)


Un avocat de langue Je ne suis pas :) et je ne joue pas non plus à la télévision.



2
votes

Parce que définir simplement remplace l'expression. Donc, vous obtenez en résultat:

b1 = (a1++)*(a1++);
b2 = (++a2)*(++a2;


2 commentaires

Vous avez ajouté des parenthèses à l'expansion. Cela ne fait aucune différence dans ce cas, mais cela fait parfois une énorme différence.


@ Darron d'accord avec vous. Pour des raisons de lisibilité ici.



3
votes

Les deux utilisations de SQ invoquent un comportement non défini, car ils attribuent à A1 et A2 plus d'une fois par point de séquence. Vous ne devez pas passer des expressions avec des effets secondaires tels que des affectations ou des incréments des macros.


0 commentaires

1
votes

Enveloppez les opérandes dans la macro entre parenthèses: xxx

également, essayez de ne pas fonctionner avec x ++ et x dans la même cession. Pourrait conduire à un comportement indéfini.

acclamations!


0 commentaires

7
votes

#define est une instruction au prétraiteur pour remplacer littéralement chaque occurrence de la macro avec son expansion. Donc, les lignes pertinentes de votre code passeront au compilateur comme suit: xxx

comme Seva States, ces expressions sont officiellement indéfinies; Mais même si nous prenons ce qui est sans doute la lecture la plus judicieuse, vous obtiendrez toujours b1 = 2 * 3; et b2 = 3 * 4; (avec les deux A1 et A2 défini sur 4 après les lignes.


0 commentaires

0
votes

Regardez le code tel qu'il sera élargi par le préprocesseur:

b1 = a1++ * a1++;
b2 = ++a2 * ++a2;


0 commentaires

1
votes

Les lignes xxx

développent xxx

qui invoquent le comportement non défini (un objet peut avoir sa valeur modifiée au plus une fois entre la séquence Points), ce qui signifie tout résultat est considéré comme "correct".

C'est le problème avec ces types de macros; Vous voulez vraiment que l'argument soit évalué une fois , mais en raison de l'expansion, elle est évaluée deux fois.

Il y a aussi le problème de l'appeler avec une expression comme < Pré> xxx

Ceci va s'étendre à xxx

ce qui n'est probablement pas ce que vous vouliez. Préserver la préséance de l'opérateur, l'expansion doit être enveloppée dans () , telle que xxx


2 commentaires

Re votre dernier point, vous devez également envelopper l'expression entière entre parenthèses, à savoir #define sq (x) ((x) * (x)) sinon expressions comme x = -sq (4 ) pourrait donner des résultats inattendus.


@Jeremyp: Oups, oui, tu as raison. Pouvez-vous dire que je n'utilise pas beaucoup de macros comme ça?



0
votes

Je ne sais vraiment pas quelle est votre question, mais peut-être que vous avez des problèmes avec votre production attendue ... Sachez que #define est un remplacement de texte "simple" qui fonctionne avant que votre code compile. Ce remplacement de texte n'a aucun respect de la portée ou des correcteurs syntaxiques. Il remplace simplement tout ce qui correspond à ce que vous avez dit. Dans votre cas, il ne ferait pas vraiment un carré du résultat de "A ++", il serait plutôt Générez ce code: B1 = A ++ * A ++;

Si vous regardez ici: Question sur C Programmation Vous pouvez voir des explications comme pourquoi " A ++ * A ++ "est un comportement officiellement indéfini.


0 commentaires

2
votes

Félicitations! Vous venez de découvrir pourquoi il est un mauvaise idée em> utiliser des macros pour ce genre de chose. En règle générale, ne faites que quelque chose une macro si elle ne peut pas être faite à l'aide d'une fonction. Dans ce cas, SQ code> pourrait facilement être implémenté comme fonction à la place:

int sq (int x)
{
    return x * x;
}


1 commentaires

+1 pour un point plus important que le langage C ++ Arcana