Question

Je veux faire une macro simple avec #define pour revenir le plus petit des deux nombres.

Comment puis-je faire cela en C? Proposer des idées, et voir si vous pouvez le rendre plus brouillées aussi.

Était-ce utile?

La solution

Pour un peu obscurcie, essayez ceci:

#define MIN(a,b)  ((((a)-(b))&0x80000000) >> 31)? (a) : (b)

En fait, il les soustractions, et regarde le bit de signe comme 1 ou 0. Si les résultats de soustraction dans un nombre négatif, le premier paramètre est plus petit.

Autres conseils

En règle générale:

#define min(a, b) (((a) < (b)) ? (a) : (b))

Soyez averti ce évalue le minimum deux fois, ce qui était la raison de la catastrophe dans une question récente .

Mais pourquoi voudriez-vous embrouiller il?


Celui-ci stocke le résultat dans une variable, et évalue que chaque argument une fois. Il est essentiellement une fonction en ligne mauvaise mans + déclaration:

#define min(t, x, a, b) \
            t x; \
            { \
                t _this_is_a_unique_name_dont_use_it_plz_0_ = a; \
                t _this_is_a_unique_name_dont_use_it_plz_1_ = b; \
                x = _this_is_a_unique_name_dont_use_it_plz_0_ < \  
                    _this_is_a_unique_name_dont_use_it_plz_1_ ? \
                    _this_is_a_unique_name_dont_use_it_plz_0_ : \  
                    _this_is_a_unique_name_dont_use_it_plz_1_ ; \
            }

utiliser comme:

min(int, x, 3, 4)
/* x is an int, equal to 3
  Just like doing:

  int x = min(3, 4);

  Without double evaluation.
*/

Et, juste pour l'enfer de celui-ci, un exemple GNU C:

#define MAX(a,b) ({ \
    typeof(a) _a_temp_; \
    typeof(b) _b_temp_; \
    _a_temp_ = (a); \
    _b_temp_ = (b); \
    _a_temp_ = _a_temp_ < _b_temp_ ? _b_temp_ : _a_temp_; \
    })

Il est pas brouillées, mais je pense que cela fonctionne pour tout type, dans un contexte, sur (presque, voir les commentaires) des arguments, etc; S'il vous plaît corriger si vous pouvez penser à des contre-exemples.

Bien sûr, vous pouvez utiliser un #define pour cela, mais pourquoi voudriez-vous? Le problème avec l'utilisation #define, même avec des parenthèses, est que vous obtenez des résultats inattendus avec le code comme ceci (d'accord, vous ne le ferez pas, mais il illustre le problème).

int result = min(a++, b++);

Si vous utilisez C ++ pas C, sûrement préférable d'utiliser une fonction en ligne, ce qui (i) évite l'évaluation des paramètres plus d'une fois, et (ii) est de type sûr (vous pouvez même fournir des versions prenant d'autres types de valeur , comme non signé, double ou chaîne).

inline int min(int a, int b) { return (a < b) ? a : b; }

Je pense que cette méthode est plutôt mignon:

#define min(a, b) (((a) + (b) - fabs((a) - (b))) * 0.5)

  

Je veux faire une macro simple avec #define pour revenir le plus petit des deux nombres.

Je voulais ajouter une solution lorsque les nombre sont virgule flottante .


Tenez compte lorsque les chiffres sont des nombres à virgule flottante et l'un des numéros est not-a-number . Ensuite, le résultat de a < b est toujours false quelle que soit la valeur de l'autre nombre.

// the result is `b` when either a or b is NaN
#define min(a, b) (((a) < (b)) ? (a) : (b))

Il peut être souhaitable que le résultat est comme ci-dessous où « arguments NaN sont traités comme des données manquantes ». C11 Note # 242

a NaN  |  b NaN  |  a < b  |  min
-------+---------+---------+---------------
No     |  No     |  No     |  b
No     |  No     |  Yes    |  a
No     |  Yes    |  .      |  a
Yes    |  No     |  .      |  b
Yes    |  Yes    |  .      |  either a or b

Pour ce faire avec une macro en C serait simple, enveloppe la fonction fmin() qui supprts le tableau ci-dessus. Code de cours devrait normalement utilisé la fonction fmin() directement.

#include <math.h>
#define my_fmin(a, b) (fmin((a), (b))

Notez que fmin(0.0, -0.0) peut retourner 0.0 ou -0.0. Ils ont tous deux égaux valeur .

Si je viens d'essayer d'obscurcir légèrement ce que je serais probablement aller avec quelque chose comme:

#define min(a,b) ((a) + ((b) < (a) ? (b) - (a) : 0))

Je pense que la solution de Doynax est assez mignon, aussi. Réservations habituelles pour les deux arguments au sujet macro en cours d'évaluation plus d'une fois.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top