Bonjour à tous et excusez-moi de vous sortir de vos
comparaîsons Python/Ruby/Java/whatever ;)
Je viens de lire un article très intéressant à propos de la conception
d'API (http://ozlabs.org/~rusty/index.cgi/tech/2008-03-30.html pour
ceux que ça intéresserait) mettant des mots sur ce qu'on pratique et
voit régulièrement. J'y suis tombé sur un exemple qui me laisse
perplexe :
---8<------------------------------------
The classic of this school is the Linux kernel min() and max() macros,
which use two GCC extensions: a statement expression which allows the
whole statement to be treated by the caller as a single expression, and
typeof which lets us declare a temporary variable of same type as
another:
/*
* min()/max() macros that also do
* strict type-checking.. See the
* "unnecessary" pointer comparison.
*/
#define min(x,y) ({ \
typeof(x) _x = (x); \
typeof(y) _y = (y); \
(void) (&_x == &_y); \
_x < _y ? _x : _y; })
Since a common error in C is to compare signed vs unsigned types and
expect a signed result, this macro insists that both types be identical.
---8<------------------------------------
Cette macro me pose 2 problèmes dont j'ai déduit la réponse à l'un
d'eux.
Tout d'abord, comme pointé dans le commentaire, pourquoi comparer
les _adresses_ des 2 variables temporaires ? Je comprends qu'on puisse
vouloir faire qu'une comparaîson échoue si 2 types sont différents
mais pour les adresses, je ne comprends pas. Un effet de bord du
compilateur ?
Enfin, c'est la forme que prend cette macro : ({...}). C'est une
construction que je n'avais pas vu (ou à laquelle je n'avais pas
prêté attention) avant. Les accolades sont, bien entendu, nécessaire
pour créer un bloc avec des variables dedans et les parenthèses sont
là pour "créer" une expression qui retournera une valeur. J'en
conclu que, la valeur retournée devant être celle de l'expression
c?a:b, le bloc "retournait" cette expression.
Est-ce un effet de bord du compilateur ?
Comment un bloc sans "return" peut-il renvoyer une valeur ?
Est-ce utilisable avec n'importe quelle autre expression ?
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
Jean-Marc Bourguet
Thomas Nemeth writes:
---8<------------------------------------ The classic of this school is the Linux kernel min() and max() macros, which use two GCC extensions: a statement expression which allows the whole statement to be treated by the caller as a single expression, and typeof which lets us declare a temporary variable of same type as another: /* * min()/max() macros that also do * strict type-checking.. See the * "unnecessary" pointer comparison. */ #define min(x,y) ({ typeof(x) _x = (x); typeof(y) _y = (y); (void) (&_x == &_y); _x < _y ? _x : _y; })
Since a common error in C is to compare signed vs unsigned types and expect a signed result, this macro insists that both types be identical. ---8<------------------------------------
Cette macro me pose 2 problèmes dont j'ai déduit la réponse à l'un d'eux.
Tout d'abord, comme pointé dans le commentaire, pourquoi comparer les _adresses_ des 2 variables temporaires ? Je comprends qu'on puisse vouloir faire qu'une comparaîson échoue si 2 types sont différents mais pour les adresses, je ne comprends pas. Un effet de bord du compilateur ?
Plutot que de comparer les types, la macro compare des variables de type pointeurs sur les types qu'on veut comparer. Si les types ne sont pas les memes, la comparaison des pointeurs sera invalides.
typeof est une des extensions de gcc dont il est question.
Enfin, c'est la forme que prend cette macro : ({...}). C'est une construction que je n'avais pas vu (ou à laquelle je n'avais pas prêté attention) avant.
C'est l'autre extension de gcc.
A+
-- Jean-Marc FAQ de fclc: http://www.isty-info.uvsq.fr/~rumeau/fclc Site de usenet-fr: http://www.usenet-fr.news.eu.org
Thomas Nemeth <thomas.nemeth@betatech.invalid> writes:
---8<------------------------------------
The classic of this school is the Linux kernel min() and max() macros,
which use two GCC extensions: a statement expression which allows the
whole statement to be treated by the caller as a single expression, and
typeof which lets us declare a temporary variable of same type as
another:
/*
* min()/max() macros that also do
* strict type-checking.. See the
* "unnecessary" pointer comparison.
*/
#define min(x,y) ({
typeof(x) _x = (x);
typeof(y) _y = (y);
(void) (&_x == &_y);
_x < _y ? _x : _y; })
Since a common error in C is to compare signed vs unsigned types and
expect a signed result, this macro insists that both types be identical.
---8<------------------------------------
Cette macro me pose 2 problèmes dont j'ai déduit la réponse à l'un
d'eux.
Tout d'abord, comme pointé dans le commentaire, pourquoi comparer
les _adresses_ des 2 variables temporaires ? Je comprends qu'on puisse
vouloir faire qu'une comparaîson échoue si 2 types sont différents
mais pour les adresses, je ne comprends pas. Un effet de bord du
compilateur ?
Plutot que de comparer les types, la macro compare des variables de type
pointeurs sur les types qu'on veut comparer. Si les types ne sont pas les
memes, la comparaison des pointeurs sera invalides.
typeof est une des extensions de gcc dont il est question.
Enfin, c'est la forme que prend cette macro : ({...}). C'est une
construction que je n'avais pas vu (ou à laquelle je n'avais pas
prêté attention) avant.
C'est l'autre extension de gcc.
A+
--
Jean-Marc
FAQ de fclc: http://www.isty-info.uvsq.fr/~rumeau/fclc
Site de usenet-fr: http://www.usenet-fr.news.eu.org
---8<------------------------------------ The classic of this school is the Linux kernel min() and max() macros, which use two GCC extensions: a statement expression which allows the whole statement to be treated by the caller as a single expression, and typeof which lets us declare a temporary variable of same type as another: /* * min()/max() macros that also do * strict type-checking.. See the * "unnecessary" pointer comparison. */ #define min(x,y) ({ typeof(x) _x = (x); typeof(y) _y = (y); (void) (&_x == &_y); _x < _y ? _x : _y; })
Since a common error in C is to compare signed vs unsigned types and expect a signed result, this macro insists that both types be identical. ---8<------------------------------------
Cette macro me pose 2 problèmes dont j'ai déduit la réponse à l'un d'eux.
Tout d'abord, comme pointé dans le commentaire, pourquoi comparer les _adresses_ des 2 variables temporaires ? Je comprends qu'on puisse vouloir faire qu'une comparaîson échoue si 2 types sont différents mais pour les adresses, je ne comprends pas. Un effet de bord du compilateur ?
Plutot que de comparer les types, la macro compare des variables de type pointeurs sur les types qu'on veut comparer. Si les types ne sont pas les memes, la comparaison des pointeurs sera invalides.
typeof est une des extensions de gcc dont il est question.
Enfin, c'est la forme que prend cette macro : ({...}). C'est une construction que je n'avais pas vu (ou à laquelle je n'avais pas prêté attention) avant.
C'est l'autre extension de gcc.
A+
-- Jean-Marc FAQ de fclc: http://www.isty-info.uvsq.fr/~rumeau/fclc Site de usenet-fr: http://www.usenet-fr.news.eu.org
Thomas Nemeth
Jean-Marc Bourguet a tapoté :
Thomas Nemeth writes:
---8<------------------------------------ /* * min()/max() macros that also do * strict type-checking.. See the * "unnecessary" pointer comparison. */ #define min(x,y) ({ typeof(x) _x = (x); typeof(y) _y = (y); (void) (&_x == &_y); _x < _y ? _x : _y; }) identical. ---8<------------------------------------
Cette macro me pose 2 problèmes dont j'ai déduit la réponse à l'un d'eux.
Tout d'abord, comme pointé dans le commentaire, pourquoi comparer les _adresses_ des 2 variables temporaires ? Je comprends qu'on puisse vouloir faire qu'une comparaîson échoue si 2 types sont différents mais pour les adresses, je ne comprends pas. Un effet de bord du compilateur ?
Plutot que de comparer les types, la macro compare des variables de type pointeurs sur les types qu'on veut comparer. Si les types ne sont pas les memes, la comparaison des pointeurs sera invalides.
Tu veux dire que le fait de _vouloir_ comparer des pointeurs sur des données de types différents lève une erreur, je suppose ? Car il me semble que des pointeurs sur des données de même type sont toujours différents du moment qu'ils ne pointent pas sur les mêmes données...
Me trompe-je ?
Merci pour tes infos.
Thomas.
Jean-Marc Bourguet a tapoté :
Thomas Nemeth <thomas.nemeth@betatech.invalid> writes:
---8<------------------------------------
/*
* min()/max() macros that also do
* strict type-checking.. See the
* "unnecessary" pointer comparison.
*/
#define min(x,y) ({
typeof(x) _x = (x);
typeof(y) _y = (y);
(void) (&_x == &_y);
_x < _y ? _x : _y; })
identical. ---8<------------------------------------
Cette macro me pose 2 problèmes dont j'ai déduit la réponse à l'un
d'eux.
Tout d'abord, comme pointé dans le commentaire, pourquoi comparer
les _adresses_ des 2 variables temporaires ? Je comprends qu'on
puisse vouloir faire qu'une comparaîson échoue si 2 types sont
différents mais pour les adresses, je ne comprends pas. Un effet de
bord du compilateur ?
Plutot que de comparer les types, la macro compare des variables de type
pointeurs sur les types qu'on veut comparer. Si les types ne sont pas
les memes, la comparaison des pointeurs sera invalides.
Tu veux dire que le fait de _vouloir_ comparer des pointeurs sur
des données de types différents lève une erreur, je suppose ? Car
il me semble que des pointeurs sur des données de même type sont
toujours différents du moment qu'ils ne pointent pas sur les mêmes
données...
---8<------------------------------------ /* * min()/max() macros that also do * strict type-checking.. See the * "unnecessary" pointer comparison. */ #define min(x,y) ({ typeof(x) _x = (x); typeof(y) _y = (y); (void) (&_x == &_y); _x < _y ? _x : _y; }) identical. ---8<------------------------------------
Cette macro me pose 2 problèmes dont j'ai déduit la réponse à l'un d'eux.
Tout d'abord, comme pointé dans le commentaire, pourquoi comparer les _adresses_ des 2 variables temporaires ? Je comprends qu'on puisse vouloir faire qu'une comparaîson échoue si 2 types sont différents mais pour les adresses, je ne comprends pas. Un effet de bord du compilateur ?
Plutot que de comparer les types, la macro compare des variables de type pointeurs sur les types qu'on veut comparer. Si les types ne sont pas les memes, la comparaison des pointeurs sera invalides.
Tu veux dire que le fait de _vouloir_ comparer des pointeurs sur des données de types différents lève une erreur, je suppose ? Car il me semble que des pointeurs sur des données de même type sont toujours différents du moment qu'ils ne pointent pas sur les mêmes données...
Me trompe-je ?
Merci pour tes infos.
Thomas.
Alain
On Tue, 01 Apr 2008 12:04:48 +0200 Thomas Nemeth wrote:
[...]
Comment un bloc sans "return" peut-il renvoyer une valeur ? Est-ce utilisable avec n'importe quelle autre expression ?
il ne renvoie pas, il a une valeur, c'est ce qui fait marcher:
a = (b = c);
et
if (a = b) { [...] }
on peut apres imaginer encore tout plein de choses bien gores =)
-- Alain
On Tue, 01 Apr 2008 12:04:48 +0200
Thomas Nemeth wrote:
[...]
Comment un bloc sans "return" peut-il renvoyer une valeur ?
Est-ce utilisable avec n'importe quelle autre expression ?
il ne renvoie pas, il a une valeur, c'est ce qui fait marcher:
a = (b = c);
et
if (a = b) {
[...]
}
on peut apres imaginer encore tout plein de choses bien gores =)
On Wed, 02 Apr 2008 09:47:26 +0200 Thomas Nemeth wrote:
Alain a tapoté :
[...]
et if (a = b) {
Qui ne devrait jamais être utilisé. C'est une trop grande source d'erreurs.
en fait on voit tres souvent une variante:
if (a = b()) { [...] }
pour assigner et tester en meme temps la valeur de retour, mais bon c'est pas mieux ;-)
-- Alain
Pierre Maurette
On Wed, 02 Apr 2008 09:47:26 +0200 Thomas Nemeth wrote:
Alain a tapoté :
[...]
et if (a = b) {
Qui ne devrait jamais être utilisé. C'est une trop grande source d'erreurs.
en fait on voit tres souvent une variante:
if (a = b()) { [...] }
pour assigner et tester en meme temps la valeur de retour, mais bon c'est pas mieux ;-)
Les compilateurs ayant en général la gentillesse d'avertir, il faut lui expliquer, ainsi qu'au relecteur, son intention. Ça vaut largement un commentaire /* affectation simultanée */:
if ((x = f()) != 0){ /* ... */ }
if ((x = y) != 0){ /* ... */ }
-- Pierre Maurette
On Wed, 02 Apr 2008 09:47:26 +0200
Thomas Nemeth wrote:
Alain a tapoté :
[...]
et
if (a = b) {
Qui ne devrait jamais être utilisé. C'est une trop grande source
d'erreurs.
en fait on voit tres souvent une variante:
if (a = b()) {
[...]
}
pour assigner et tester en meme temps la valeur de retour, mais bon
c'est pas mieux ;-)
Les compilateurs ayant en général la gentillesse d'avertir, il faut lui
expliquer, ainsi qu'au relecteur, son intention. Ça vaut largement un
commentaire /* affectation simultanée */:
On Wed, 02 Apr 2008 09:47:26 +0200 Thomas Nemeth wrote:
Alain a tapoté :
[...]
et if (a = b) {
Qui ne devrait jamais être utilisé. C'est une trop grande source d'erreurs.
en fait on voit tres souvent une variante:
if (a = b()) { [...] }
pour assigner et tester en meme temps la valeur de retour, mais bon c'est pas mieux ;-)
Les compilateurs ayant en général la gentillesse d'avertir, il faut lui expliquer, ainsi qu'au relecteur, son intention. Ça vaut largement un commentaire /* affectation simultanée */:
if ((x = f()) != 0){ /* ... */ }
if ((x = y) != 0){ /* ... */ }
-- Pierre Maurette
Erwan David
Alain écrivait :
en fait on voit tres souvent une variante:
if (a = b()) { [...] }
pour assigner et tester en meme temps la valeur de retour, mais bon c'est pas mieux ;-)
if((a = f()) == val) { [....] }
est assezlisible quand même.
-- Le travail n'est pas une bonne chose. Si ça l'était, les riches l'auraient accaparé
Alain <alain@nospam.com.invalid> écrivait :
en fait on voit tres souvent une variante:
if (a = b()) {
[...]
}
pour assigner et tester en meme temps la valeur de retour, mais bon
c'est pas mieux ;-)
if((a = f()) == val)
{
[....]
}
est assezlisible quand même.
--
Le travail n'est pas une bonne chose. Si ça l'était,
les riches l'auraient accaparé