Other operators
Una colección de operadores que no encajan en ninguna de las otras categorías principales.
|
Esta sección está incompleta
Razón: considerar un índice de contenidos más general para esta y otras tablas que cubren múltiples temas |
| Operador | Nombre del operador | Ejemplo | Descripción |
|---|---|---|---|
| ( ... ) | llamada de función | f ( ... ) | llama a la función f (), con cero o más argumentos |
| , | operador coma | a, b | evalúa la expresión a , ignora su valor de retorno y completa cualquier efecto secundario, luego evalúa la expresión b , devolviendo el tipo y el resultado de esta evaluación |
| ( type ) | conversión de tipo | ( type ) a | convierte el tipo de a a type |
| ? : | operador condicional | a ? b : c | si a es lógicamente verdadero (no se evalúa a cero) entonces evalúa la expresión b , de lo contrario evalúa la expresión c |
| sizeof | operador sizeof | sizeof a | el tamaño en bytes de a |
|
_Alignof
(desde C11) |
operador _Alignof | _Alignof ( type ) | la alineación requerida de type |
| typeof | operadores typeof | typeof ( a ) | el tipo de a |
Contenidos |
Llamada de función
La expresión de llamada a función tiene la forma
expresión
(
lista-de-argumentos
(opcional)
)
|
|||||||||
donde
| expression | - | cualquier expresión de tipo puntero-a-función (después de las conversiones de lvalue ) |
| argument-list | - | lista separada por comas de expresiones (que no pueden ser operadores coma) de cualquier tipo de objeto completo. Puede omitirse al llamar funciones que no toman argumentos. |
El comportamiento de la expresión de llamada a función depende de si el prototipo de la función que se llama está en alcance en el punto de la llamada.
Llamada a una función con un prototipo
|
Adicionalmente, para cada parámetro de
tipo array
que utilice la palabra clave
static
entre
[
y
]
, la expresión de argumento debe designar un puntero al elemento de un array con al menos tantos elementos como se especifica en la expresión de tamaño del parámetro.
|
(desde C99) |
-
- si hay un parámetro de puntos suspensivos finales , Promociones de argumentos predeterminadas se realizan en los argumentos restantes, que están disponibles para va_list .
void f(char* p, int x) {} int main(void) { f("abc", 3.14); // array to pointer and float to int conversions }
Llamada a una función sin prototipo
1)
Los argumentos son evaluados
en orden no especificado y sin secuenciación
.
2)
Promociones de argumentos por defecto
se realizan en cada expresión de argumento.
3)
Asignación
se realiza para copiar el valor de cada argumento al parámetro de función correspondiente, ignorando cualquier calificador de tipo en el tipo del parámetro y sus posibles elementos o miembros recursivos, si los hay.
4)
La función se ejecuta, y el valor que devuelve se convierte en el valor de la expresión de llamada a función (si la función devuelve void, la expresión de llamada a función es una expresión 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) {} El comportamiento de una llamada a función sin prototipo es indefinido si
|
(hasta C23) |
Notas
Las evaluaciones de expression que designa la función a llamar y todos los argumentos están sin secuenciar entre sí (pero hay un punto de secuencia antes de que comience la ejecución del cuerpo de la función)
(*pf[f1()]) (f2(), f3() + f4()); // f1, f2, f3, f4 pueden ser llamadas en cualquier orden
Aunque la llamada a función solo está definida para punteros a funciones, funciona con designadores de función debido a la conversión implícita de función a puntero .
int f(void) { return 1; } int (*pf)(void) = f; int main(void) { f(); // convertir f a puntero, luego llamar (&f)(); // crear un puntero a función, luego llamar pf(); // llamar la función (*pf)(); // obtener el designador de función, convertir a puntero, luego llamar (****f)(); // convertir a puntero, obtener la función, repetir 4x, luego llamar (****pf)(); // también correcto }
Las funciones que ignoran argumentos no utilizados, como printf , deben ser llamadas con un prototipo en alcance (el prototipo de dichas funciones necesariamente utiliza el parámetro de puntos suspensivos finales ) para evitar invocar comportamiento indefinido.
La redacción actual estándar de la semántica de preparación de parámetros de función es defectuosa, porque especifica que los parámetros se asignan desde argumentos durante la llamada, lo cual rechaza incorrectamente tipos de parámetros o miembros calificados como const, y aplica inapropiadamente la semántica de volatile que es inimplementable para parámetros de función en muchas plataformas. Un reporte de defecto post-C11 DR427 propuso cambiar dicha semántica de asignación a inicialización, pero fue cerrado como no-defecto.
|
Una expresión de llamada a función donde expression consiste completamente en un identificador y ese identificador no está declarado actúa como si el identificador se declarara como extern int identifier(); // returns int and has no prototype Por lo tanto, el siguiente programa completo es válido en C89: main() { int n = atoi("123"); // implicitly declares atoi as int atoi() } |
(hasta C99) |
Operador coma
La expresión del operador coma tiene la forma
lhs
,
rhs
|
|||||||||
donde
| lhs | - | cualquier expresión |
| rhs | - | cualquier expresión excepto otro operador coma (en otras palabras, la asociatividad del operador coma es de izquierda a derecha) |
Primero, el operando izquierdo, lhs , es evaluado y su valor resultante es descartado.
Entonces, tiene lugar un punto de secuencia , de modo que todos los efectos secundarios de lhs se completan.
Luego, el operando derecho, rhs , es evaluado y su resultado es devuelto por el operador coma como un no-lvalue .
Notas
El tipo del lhs puede ser void (es decir, puede ser una llamada a una función que devuelve void , o puede ser una expresión cast a void )
El operador coma puede ser lvalue en C++, pero nunca en C
El operador coma puede devolver una estructura (las únicas otras expresiones que devuelven estructuras son los literales compuestos, las llamadas a funciones, las asignaciones y el operador condicional)
En los siguientes contextos, el operador coma no puede aparecer en el nivel superior de una expresión porque la coma tiene un significado diferente:
- lista de argumentos en una llamada a función
- expresión de inicialización o lista de inicialización
- selección genérica
Si el operador coma debe utilizarse en tal contexto, debe ir entre paréntesis:
// int n = 2,3; // error, se asume que la coma comienza el siguiente declarador // int a[2] = {1,2,3}; // error: más inicializadores que elementos int n = (2,3), a[2] = {(1,2),3}; // OK f(a, (t=3, t+2), c); // OK, primero almacena 3 en t, luego llama a f con tres argumentos
El operador coma de nivel superior también está prohibido en los límites de array
// int a[2,3]; // error int a[(2,3)]; // OK, VLA array de tamaño 3 (VLA porque (2,3) no es una expresión constante)
El operador coma no está permitido en expresiones constantes , independientemente de si está en el nivel superior o no
// static int n = (1,2); // Error: la expresión constante no puede llamar al operador coma
Operador de conversión
Ver cast operator
Operador condicional
La expresión del operador condicional tiene la forma
condición
?
expresión-verdadera
:
expresión-falsa
|
|||||||||
donde
| condition | - | una expresión de tipo escalar |
| expression-true | - | la expresión que será evaluada si condition se compara como diferente de cero |
| expression-false | - | la expresión que será evaluada si condition se compara como igual a cero |
Solo las siguientes expresiones están permitidas como expression-true y expression-false
- dos expresiones de cualquier tipo aritmético
- dos expresiones del mismo struct o union tipo
- dos expresiones de tipo void
- dos expresiones de tipo puntero, que apuntan a tipos que son compatibles , ignorando calificadores cvr
|
(desde C23) |
- una expresión es un puntero y la otra es la constante de puntero nulo (como NULL ) o un valor de tipo nullptr_t (desde C23)
- una expresión es un puntero a objeto y la otra es un puntero a void (posiblemente calificado)
| (desde C23) |
#define ICE(x) (sizeof(*(1 ? ((void*)((x) * 0l)) : (int*)1))) // si x es una Expresión Constante Entera entonces la macro se expande a sizeof(*(1 ? NULL : (int *) 1)) // (void *)((x)*0l)) -> NULL // de acuerdo con el punto (4) esto se convierte adicionalmente en sizeof(int) // si x no es una Expresión Constante Entera entonces la macro se expande a // de acuerdo con el punto (6) (sizeof(*(void *)(x)) // Error debido a tipo incompleto
Notas
El operador condicional nunca es una expresión lvalue , aunque puede retornar objetos de tipo struct/union. Las únicas otras expresiones que pueden retornar structs son assignment , comma , function call , y compound literal .
Tenga en cuenta que en C++, puede ser una expresión lvalue.
Consulte precedencia de operadores para los detalles sobre la precedencia relativa de este operador y la asignación.
El operador condicional tiene asociatividad de derecha a izquierda, lo que permite encadenamiento
#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
operador
Ver operador sizeof
_Alignof
operador
typeof
operadores
Referencias
- Estándar C23 (ISO/IEC 9899:2024):
-
- 6.5.2.2 Llamadas a función (p: TBD)
-
- 6.5.3.4 Operadores sizeof y _Alignof (p: TBD)
-
- 6.5.4 Operadores de conversión (p: TBD)
-
- 6.5.15 Operador condicional (p: TBD)
-
- 6.5.17 Operador coma (p: TBD)
-
- 6.7.3.5 Especificadores typeof (p: 115-118)
- Estándar C17 (ISO/IEC 9899:2018):
-
- 6.5.2.2 Llamadas a función (p: 58-59)
-
- 6.5.3.4 Operadores sizeof y _Alignof (p: 64-65)
-
- 6.5.4 Operadores de conversión (p: 65-66)
-
- 6.5.15 Operador condicional (p: 71-72)
-
- 6.5.17 Operador coma (p: 75)
- Estándar C11 (ISO/IEC 9899:2011):
-
- 6.5.2.2 Llamadas a función (p: 81-82)
-
- 6.5.3.4 Los operadores sizeof y _Alignof (p: 90-91)
-
- 6.5.4 Operadores de conversión (p: 91)
-
- 6.5.15 Operador condicional (p: 100)
-
- 6.5.17 Operador coma (p: 105)
- Estándar C99 (ISO/IEC 9899:1999):
-
- 6.5.2.2 Llamadas a función (p: 71-72)
-
- 6.5.3.4 El operador sizeof (p: 80-81)
-
- 6.5.4 Operadores de conversión (p: 81)
-
- 6.5.15 Operador condicional (p: 90-91)
-
- 6.5.17 Operador coma (p: 94)
- Estándar C89/C90 (ISO/IEC 9899:1990):
-
- 3.3.2.2 Llamadas a funciones
-
- 3.3.3.4 El operador sizeof
-
- 3.3.4 Operadores de conversión
-
- 3.3.15 Operador condicional
-
- 3.3.17 Operador coma
Véase también
| Operadores comunes | ||||||
|---|---|---|---|---|---|---|
| asignación |
incremento
decremento |
aritméticos | lógicos | comparación |
acceso a
miembros |
otros |
|
a
=
b
|
++
a
|
+
a
|
!
a
|
a
==
b
|
a
[
b
]
|
a
(
...
)
|
|
Documentación de C++
para
Otros operadores
|