Où sont MIN
y MAX
définie en C, si elle existe ?
Quelle est la meilleure façon de les implémenter, de manière aussi générique et sûre que possible ? (De préférence, extensions de compilateurs ou buildins pour les compilateurs grand public).
Où sont MIN
y MAX
définie en C, si elle existe ?
Quelle est la meilleure façon de les implémenter, de manière aussi générique et sûre que possible ? (De préférence, extensions de compilateurs ou buildins pour les compilateurs grand public).
Où sont
MIN
yMAX
définie en C, si elle existe ?
Ils ne le sont pas.
Quelle est la meilleure façon de les implémenter, de la manière la plus générique et la plus sûre possible (extensions de compilateurs/compléments pour les compilateurs courants de préférence) ?
En tant que fonctions. Je n'utiliserais pas de macros comme #define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
surtout si vous envisagez de déployer votre code. Soit vous écrivez votre propre code, soit vous utilisez quelque chose comme le standard fmax
o fmin
ou corrigez la macro en utilisant Le type de GCC (vous bénéficiez également d'une prime de sécurité type) dans un centre d'hébergement. Expression de la déclaration GCC :
#define max(a,b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a > _b ? _a : _b; })
Tout le monde dit "oh, je connais la double évaluation, ce n'est pas un problème" et quelques mois plus tard, vous devrez déboguer les problèmes les plus stupides pendant des heures.
Notez l'utilisation de __typeof__
au lieu de typeof
:
Si vous écrivez un fichier d'en-tête qui doit fonctionner lorsqu'il est inclus dans des programmes ISO C ISO, écrivez
__typeof__
au lieu detypeof
.
Vous savez, ce serait bien pratique si gcc avait un avertissement du genre : warning: expression with side-effects multiply evaluated by macro
au point d'utilisation...
@caf : cela ne nécessiterait-il pas que le préprocesseur ait une connaissance plus complexe de la syntaxe C ?
@dreamlax : Je pensais que le préprocesseur pourrait laisser des annotations au point de chaque expansion de macro lorsqu'un paramètre est utilisé plus d'une fois, que le compilateur pourrait alors utiliser.
Il est également fourni dans les versions GNU libc (Linux) et FreeBSD de sys/param.h
et a la définition fournie par dreamlax.
Sur Debian :
$ uname -sr
Linux 2.6.11
$ cat /etc/debian_version
5.0.2
$ egrep 'MIN\(|MAX\(' /usr/include/sys/param.h
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
$ head -n 2 /usr/include/sys/param.h | grep GNU
This file is part of the GNU C Library.
Sur FreeBSD :
$ uname -sr
FreeBSD 5.5-STABLE
$ egrep 'MIN\(|MAX\(' /usr/include/sys/param.h
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
Les dépôts de sources sont ici :
J'ai ajouté les définitions des systèmes auxquels j'ai accès dans ma réponse ci-dessus (le champ de commentaire n'accepte pas le formatage, pour autant que je sache). Je vais essayer de trouver les liens vers les dépôts de sources FreeBSD/Linux/glibc.
+1. Très bien. Fonctionne pour openSUSE/Linux 3.1.0-1.2-desktop
/ gcc version 4.6.2 (SUSE Linux)
aussi. :) Dommage que ce ne soit pas portable.
Il y a un std::min
y std::max
en C++, mais AFAIK, il n'y a pas d'équivalent dans la bibliothèque standard du C. Vous pouvez les définir vous-même avec des macros comme
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
Mais cela pose des problèmes si vous écrivez quelque chose comme MAX(++a, ++b)
.
Pourquoi mettre trop de parenthèses ? ?? J'ai trouvé un quiz où ils ont dit #define MIN(A, B) ((A < B) ? A : B)
n'est pas un moyen flexible, pourquoi ?
@Makouda : Les parenthèses supplémentaires dans les macros permettent d'éviter les problèmes de précédence des opérateurs. Par exemple, considérez #define MULT(x, y) x * y
. Ensuite, MULT(a + b, a + b)
s'étend à a + b * a + b
qui se traduit par a + (b * a) + b
en raison de la préséance. Ce n'est probablement pas ce que le programmeur voulait.
Je ne pense pas qu'il s'agisse de macros standardisées. Il existe déjà des fonctions standardisées pour la virgule flottante, fmax
y fmin
(et fmaxf
pour les flotteurs, et fmaxl
pour les doubles longs).
Vous pouvez les mettre en œuvre sous forme de macros, à condition d'être conscient des problèmes d'effets secondaires et de double évaluation.
#define MAX(a,b) ((a) > (b) ? a : b)
#define MIN(a,b) ((a) < (b) ? a : b)
Dans la plupart des cas, vous pouvez laisser au compilateur le soin de déterminer ce que vous essayez de faire et de l'optimiser du mieux qu'il peut. Bien que cela pose des problèmes lorsqu'il est utilisé comme MAX(i++, j++)
Je doute qu'il soit nécessaire de vérifier le maximum de valeurs incrémentées en une seule fois. Incrémentez d'abord, puis vérifiez.
Cette réponse devrait être privilégiée car il existe clairement des fonctions min et max dans la bibliothèque mathématique : cplusplus.com/reference/cmath/fmax
@imranal De quoi parlez-vous exactement ? Le site mise en œuvre code de ces bibliothèques ? Mais ce code n'est pas exposé En d'autres termes, ils ne le placent pas dans l'interface de la bibliothèque, qui est potentiellement dangereuse.
@Antonio Je pense que vous utilisez des définitions incorrectes de "exposé" et "interface". L'interface d'une bibliothèque c est constituée des variables, types, macros et déclarations de fonctions externalisés dans un fichier d'en-tête ; fmin/fmax sont déclarés dans le fichier d'en-tête, on dit donc qu'ils sont exposés. Je ne suis pas sûr de ce que vous considérez comme dangereux.
J'ai écrit ceci version qui fonctionne pour MSVC, GCC, C et C++.
#if defined(__cplusplus) && !defined(__GNUC__)
# include <algorithm>
# define MIN std::min
# define MAX std::max
//# define TMIN(T, a, b) std::min<T>(a, b)
//# define TMAX(T, a, b) std::max<T>(a, b)
#else
# define _CHOOSE2(binoper, lexpr, lvar, rexpr, rvar) \
({ \
decltype(lexpr) lvar = (lexpr); \
decltype(rexpr) rvar = (rexpr); \
lvar binoper rvar ? lvar : rvar; \
})
# define _CHOOSE_VAR2(prefix, unique) prefix##unique
# define _CHOOSE_VAR(prefix, unique) _CHOOSE_VAR2(prefix, unique)
# define _CHOOSE(binoper, lexpr, rexpr) \
_CHOOSE2( \
binoper, \
lexpr, _CHOOSE_VAR(_left, __COUNTER__), \
rexpr, _CHOOSE_VAR(_right, __COUNTER__) \
)
# define MIN(a, b) _CHOOSE(<, a, b)
# define MAX(a, b) _CHOOSE(>, a, b)
#endif
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.
3 votes
Quelqu'un peut-il vérifier ce et dire si c'est une macro ou une fonction ? J'entends par là que, dans la ligne
min(x++, y++)
, x et y sont incrémentés une ou deux fois si j'utilise cecimin
.