Other operators
Une collection d'opérateurs qui ne s'inscrivent dans aucune des autres catégories majeures.
|
Cette section est incomplète
Motif : envisager un sommaire plus polyvalent pour ce tableau et d'autres couvrant plusieurs sujets |
| Opérateur | Nom de l'opérateur | Exemple | Description |
|---|---|---|---|
| ( ... ) | Appel de fonction | f ( ... ) | Appelle la fonction f (), avec zéro ou plusieurs arguments |
| , | Opérateur virgule | a, b | Évalue l'expression a , ignore sa valeur de retour et complète tous les effets secondaires, puis évalue l'expression b , renvoyant le type et le résultat de cette évaluation |
| ( type ) | Conversion de type | ( type ) a | Convertit le type de a en type |
| ? : | Opérateur conditionnel | a ? b : c | Si a est logiquement vrai (n'évalue pas à zéro) alors évalue l'expression b , sinon évalue l'expression c |
| sizeof | Opérateur sizeof | sizeof a | La taille en octets de a |
|
_Alignof
(depuis C11) |
Opérateur _Alignof | _Alignof ( type ) | L'alignement requis pour type |
| typeof | Opérateurs typeof | typeof ( a ) | Le type de a |
Table des matières |
Appel de fonction
L'expression d'appel de fonction a la forme
expression
(
liste-arguments
(optionnel)
)
|
|||||||||
où
| expression | - | toute expression de type pointeur-vers-fonction (après conversions de lvalue ) |
| argument-list | - | liste d'expressions séparées par des virgules (qui ne peuvent pas être des opérateurs virgule) de tout type d'objet complet. Peut être omise lors de l'appel de fonctions qui ne prennent aucun argument. |
Le comportement de l'expression d'appel de fonction dépend de si le prototype de la fonction appelée est dans la portée au point d'appel.
Appel à une fonction avec un prototype
|
De plus, pour chaque paramètre de
type tableau
qui utilise le mot-clé
static
entre
[
et
]
, l'expression d'argument doit désigner un pointeur vers l'élément d'un tableau ayant au moins autant d'éléments que spécifié dans l'expression de taille du paramètre.
|
(depuis C99) |
-
- s'il y a un paramètre trailing ellipsis , Default argument promotions sont effectuées sur les arguments restants, qui sont rendus disponibles à va_list .
void f(char* p, int x) {} int main(void) { f("abc", 3.14); // array to pointer and float to int conversions }
Appel à une fonction sans prototype
1)
Les arguments sont évalués
dans un ordre non spécifié et sans séquencement
.
2)
Les promotions d'arguments par défaut
sont effectuées sur chaque expression d'argument.
3)
Une affectation
est réalisée pour copier la valeur de chaque argument vers le paramètre de fonction correspondant, en ignorant tout qualificateur de type sur le type du paramètre et ses éléments ou membres éventuellement récursifs, s'il y en a.
4)
La fonction est exécutée, et la valeur qu'elle retourne devient la valeur de l'expression d'appel de fonction (si la fonction retourne void, l'expression d'appel de fonction est une expression void)
void f(); // no prototype int main(void) { f(1, 1.0f); // UB unless f is defined to take an int and a double } void f(int a, double c) {} Le comportement d'un appel de fonction sans prototype est indéfini si
|
(jusqu'à C23) |
Notes
Les évaluations de expression qui désigne la fonction à appeler et de tous les arguments sont non-séquencées les unes par rapport aux autres (mais il y a un point de séquence avant que le corps de la fonction ne commence à s'exécuter)
(*pf[f1()]) (f2(), f3() + f4()); // f1, f2, f3, f4 peuvent être appelées dans n'importe quel ordre
Bien que l'appel de fonction ne soit défini que pour les pointeurs vers des fonctions, il fonctionne avec les désignateurs de fonction grâce à la conversion implicite fonction-vers-pointeur .
int f(void) { return 1; } int (*pf)(void) = f; int main(void) { f(); // convertit f en pointeur, puis appelle (&f)(); // crée un pointeur vers fonction, puis appelle pf(); // appelle la fonction (*pf)(); // obtient le désignateur de fonction, convertit en pointeur, puis appelle (****f)(); // convertit en pointeur, obtient la fonction, répète 4x, puis appelle (****pf)(); // également OK }
Les fonctions qui ignorent les arguments inutilisés, telles que printf , doivent être appelées avec un prototype dans la portée (le prototype de ces fonctions utilise nécessairement le paramètre ellipses de fin ) pour éviter d'invoquer un comportement indéfini.
La formulation actuelle de la norme concernant la sémantique de préparation des paramètres de fonction est défectueuse, car elle spécifie que les paramètres sont assignés à partir des arguments lors de l'appel, ce qui rejette incorrectement les types de paramètres ou membres qualifiés const, et applique inappropriément la sémantique de volatile qui est irréalisable pour les paramètres de fonction sur de nombreuses plateformes. Un rapport de défaut post-C11 DR427 a proposé de modifier cette sémantique d'assignation en initialisation, mais a été clos comme n'étant pas un défaut.
|
Une expression d'appel de fonction où expression consiste entièrement en un identifiant et que cet identifiant n'est pas déclaré agit comme si l'identifiant était déclaré comme extern int identifier(); // returns int and has no prototype Ainsi le programme complet suivant est valide en C89 : main() { int n = atoi("123"); // implicitly declares atoi as int atoi() } |
(jusqu'à C99) |
Opérateur virgule
L'expression de l'opérateur virgule a la forme
lhs
,
rhs
|
|||||||||
où
| lhs | - | toute expression |
| rhs | - | toute expression autre qu'un autre opérateur virgule (en d'autres termes, l' associativité de l'opérateur virgule est de gauche à droite) |
D'abord, l'opérande gauche, lhs , est évalué et sa valeur résultante est ignorée.
Ensuite, un point de séquence intervient, de sorte que tous les effets secondaires de lhs soient terminés.
Ensuite, l'opérande droit, rhs , est évalué et son résultat est retourné par l'opérateur virgule en tant que non-lvalue .
Notes
Le type du lhs peut être void (c'est-à-dire qu'il peut s'agir d'un appel à une fonction qui retourne void , ou il peut s'agir d'une expression cast vers void )
L'opérateur virgule peut être une lvalue en C++, mais jamais en C
L'opérateur virgule peut renvoyer une structure (les seules autres expressions qui renvoient des structures sont les littéraux composés, les appels de fonction, les assignations et l'opérateur conditionnel)
Dans les contextes suivants, l'opérateur virgule ne peut pas apparaître au niveau supérieur d'une expression car la virgule a une signification différente :
- liste d'arguments dans un appel de fonction
- expression d'initialisation ou liste d'initialisation
- sélection générique
Si l'opérateur virgule doit être utilisé dans un tel contexte, il doit être mis entre parenthèses :
// int n = 2,3; // erreur, la virgule est supposée commencer le déclarateur suivant // int a[2] = {1,2,3}; // erreur : plus d'initialiseurs que d'éléments int n = (2,3), a[2] = {(1,2),3}; // OK f(a, (t=3, t+2), c); // OK, d'abord, stocke 3 dans t, puis appelle f avec trois arguments
L'opérateur virgule de premier niveau est également interdit dans les bornes des tableaux
// int a[2,3]; // erreur int a[(2,3)]; // OK, tableau VLA de taille 3 (VLA car (2,3) n'est pas une expression constante)
L'opérateur virgule n'est pas autorisé dans les expressions constantes , qu'il soit au niveau supérieur ou non
// static int n = (1,2); // Erreur : une expression constante ne peut pas appeler l'opérateur virgule
Opérateur de cast
Voir cast operator
Opérateur conditionnel
L'expression de l'opérateur conditionnel a la forme
condition
?
expression-vraie
:
expression-fausse
|
|||||||||
où
| condition | - | une expression de type scalaire |
| expression-true | - | l'expression qui sera évaluée si la condition est différente de zéro |
| expression-false | - | l'expression qui sera évaluée si la condition est égale à zéro |
Seules les expressions suivantes sont autorisées comme expression-true et expression-false
- deux expressions de tout type arithmétique
- deux expressions du même struct ou union type
- deux expressions de type void
- deux expressions de type pointeur, pointant vers des types compatibles , en ignorant les qualificatifs cvr
|
(depuis C23) |
- une expression est un pointeur et l'autre est la constante de pointeur nul (telle que NULL ) ou une valeur nullptr_t (depuis C23)
- une expression est un pointeur vers objet et l'autre est un pointeur vers void (éventuellement qualifié)
| (depuis C23) |
#define ICE(x) (sizeof(*(1 ? ((void*)((x) * 0l)) : (int*)1))) // si x est une Expression Constante Entière alors la macro se développe en sizeof(*(1 ? NULL : (int *) 1)) // (void *)((x)*0l)) -> NULL // selon le point (4) cela se convertit ensuite en sizeof(int) // si x n'est pas une Expression Constante Entière alors la macro se développe en // selon le point (6) (sizeof(*(void *)(x)) // Erreur due au type incomplet
Notes
L'opérateur conditionnel n'est jamais une expression lvalue , bien qu'il puisse retourner des objets de type struct/union. Les seules autres expressions pouvant retourner des structures sont l'affectation , la virgule , l'appel de fonction , et le littéral composé .
Notez qu'en C++, il peut s'agir d'une expression lvalue.
Voir la précédence des opérateurs pour les détails sur la précédence relative de cet opérateur et de l'affectation.
L'opérateur conditionnel a une associativité de droite à gauche, ce qui permet l'enchaînement
#include <assert.h> enum vehicle { bus, airplane, train, car, horse, feet }; enum vehicle choose(char arg) { return arg == 'B' ? bus : arg == 'A' ? airplane : arg == 'T' ? train : arg == 'C' ? car : arg == 'H' ? horse : feet ; } int main(void) { assert(choose('H') == horse && choose('F') == feet); }
sizeof
opérateur
Voir sizeof operator
_Alignof
opérateur
Voir opérateur _Alignof
typeof
opérateurs
Voir opérateurs typeof
Références
- Norme C23 (ISO/CEI 9899:2024) :
-
- 6.5.2.2 Appels de fonction (p: TBD)
-
- 6.5.3.4 Opérateurs sizeof et _Alignof (p: TBD)
-
- 6.5.4 Opérateurs de cast (p: TBD)
-
- 6.5.15 Opérateur conditionnel (p: TBD)
-
- 6.5.17 Opérateur virgule (p: TBD)
-
- 6.7.3.5 Spécificateurs typeof (p: 115-118)
- Norme C17 (ISO/CEI 9899:2018) :
-
- 6.5.2.2 Appels de fonction (p: 58-59)
-
- 6.5.3.4 Opérateurs sizeof et _Alignof (p: 64-65)
-
- 6.5.4 Opérateurs de cast (p: 65-66)
-
- 6.5.15 Opérateur conditionnel (p: 71-72)
-
- 6.5.17 Opérateur virgule (p: 75)
- Norme C11 (ISO/CEI 9899:2011) :
-
- 6.5.2.2 Appels de fonction (p: 81-82)
-
- 6.5.3.4 Opérateurs sizeof et _Alignof (p: 90-91)
-
- 6.5.4 Opérateurs de cast (p: 91)
-
- 6.5.15 Opérateur conditionnel (p: 100)
-
- 6.5.17 Opérateur virgule (p: 105)
- Norme C99 (ISO/CEI 9899:1999) :
-
- 6.5.2.2 Appels de fonction (p. 71-72)
-
- 6.5.3.4 L'opérateur sizeof (p. 80-81)
-
- 6.5.4 Opérateurs de cast (p. 81)
-
- 6.5.15 Opérateur conditionnel (p. 90-91)
-
- 6.5.17 Opérateur virgule (p. 94)
- Norme C89/C90 (ISO/CEI 9899:1990) :
-
- 3.3.2.2 Appels de fonction
-
- 3.3.3.4 L'opérateur sizeof
-
- 3.3.4 Opérateurs de cast
-
- 3.3.15 Opérateur conditionnel
-
- 3.3.17 Opérateur virgule
Voir aussi
| Opérateurs courants | ||||||
|---|---|---|---|---|---|---|
| affectation |
incrémentation
décrémentation |
arithmétique | logique | comparaison | accès membre | autres |
|
a
=
b
|
++
a
|
+
a
|
!
a
|
a
==
b
|
a
[
b
]
|
a
(
...
)
|
|
Documentation C++
pour
Autres opérateurs
|