Ce que fait le `` opérateur do en C ?
Réponses
Trop de publicités?J’ai vu la plupart utilisée dans `` boucles :
String s ; tout en (read_string(s), s.len() > 5) { //do quelque chose }
Il va faire l’opération, puis faire un test basé sur un effet secondaire. L’autre façon serait de le faire comme ceci :
String s ; read_string(s) ; while(s.Len() > 5) { //do quelque chose read_string(s) ; }
L' opérateur virgule permettra d'évaluer l'opérande de gauche, jeter le résultat et d'en évaluer l'opérande de droite et qui sera le résultat. Le idiomatiques utiliser comme indiqué dans le lien est lors de l'initialisation des variables utilisées dans un for
boucle, et il donne l'exemple suivant:
void rev(char *s, size_t len)
{
char *first;
for ( first = s, s += len - 1; s >= first; --s)
/*^^^^^^^^^^^^^^^^^^^^^^^*/
putchar(*s);
}
Sinon il n'y a pas beaucoup de grands usages de l' opérateur virgule, même si il est facile de l'abus de générer le code qui est difficile à lire et à maintenir.
À partir du projet de standard C99 la grammaire est comme suit:
expression:
assignment-expression
expression , assignment-expression
et l'alinéa 2 dit:
L' opérande de gauche d'un opérateur virgule est évalué comme un vide d'expression, il y a un point de séquence après son évaluation. Puis l' opérande de droite est évaluée; le résultat a son type et sa valeur. 97) Si une tentative est faite pour modifier le résultat d'un opérateur virgule ou d'y accéder après le prochain point de séquence, le comportement est indéfini.
Note de bas de page 97 dit:
Un opérateur virgule ne donnent pas une lvalue.
ce qui signifie que vous ne pouvez pas affecter le résultat de l' opérateur virgule.
L'opérateur virgule combine les deux expressions de chaque côté en un seul, de les évaluer à la fois de gauche à droite. La valeur de la main droite est retourné en tant que valeur de l'expression complète.
-
(expr1, expr2)
, c'est comme(expr1 && expr2)
mais les deuxexpr1
etexpr2
seront toujours évaluées, quelle que soitexpr1
de rendement. -
(expr1, expr2)
, c'est comme{ expr1; expr2; }
, mais il peut être utilisé comme une expression dans un appel de fonction ou de la cession.
Il est souvent vu en for
boucles d'initialiser ou de maintenir de multiples variables comme ceci:
for (low = 0, high = MAXSIZE; low < high; low = newlow, high = newhigh)
{
/* do something with low and high and put new values
in newlow and newhigh */
}
En dehors de cela, je ne l'ai utilisé "en colère" dans les autres cas, lorsque l'emballage jusqu'à deux opérations qui devraient toujours aller de pair dans une macro. Nous avons eu code copié différentes valeurs binaires dans un tampon d'octets pour l'envoi sur un réseau, et un pointeur maintenue lorsque nous avons eu jusqu'à:
unsigned char outbuff[BUFFSIZE];
unsigned char *ptr = outbuff;
*ptr++ = first_byte_value;
*ptr++ = second_byte_value;
send_buff(outbuff, (int)(ptr - outbuff));
Où les valeurs ont été short
s ou int
s nous l'avons fait:
*((short *)ptr)++ = short_value;
*((int *)ptr)++ = int_value;
Plus tard, nous avons lu que ce n'était pas vraiment valide en C, car (short *)ptr
n'est plus une l-value et ne peut pas être incrémenté, bien que notre compilateur à la fois, n'a pas l'esprit. Pour résoudre ce problème, nous avons divisé l'expression en deux:
*(short *)ptr = short_value;
ptr += sizeof(short);
Cependant, cette approche se fondait sur tous les développeurs à se rappeler de mettre les deux états, dans tous les temps. Nous voulions une fonction où l'on pouvait passer le pointeur de sortie, la valeur et le type de la valeur. Ceci étant C, pas du C++ à l'aide de modèles, nous ne pourrions pas avoir une prise de fonction d'un type arbitraire, de sorte que nous nous sommes installés sur une macro:
#define ASSIGN_INCR(p, val, type) ((*((type) *)(p) = (val)), (p) += sizeof(type))
En utilisant l'opérateur virgule, nous avons été en mesure de l'utiliser dans des expressions ou des énoncés comme nous l'avions souhaité:
if (need_to_output_short)
ASSIGN_INCR(ptr, short_value, short);
latest_pos = ASSIGN_INCR(ptr, int_value, int);
send_buff(outbuff, (int)(ASSIGN_INCR(ptr, last_value, int) - outbuff));
Je ne dis pas que l'un de ces exemples sont un bon style! En effet, je crois me souvenir de Steve McConnell Code Complet de conseiller à l'encontre même de l'aide de la virgule opérateurs en for
boucle: pour la lisibilité et la maintenabilité, la boucle doit être contrôlé par une seule variable, et les expressions dans l' for
ligne elle-même ne doit contenir que la boucle de contrôle de code, pas d'autres morceaux de l'initialisation ou de la boucle de l'entretien.