Namespaces
Variants

Constant expressions

From cppreference.net

Varias variedades de expresiones se conocen como constant expressions .

Contenidos

Expresión constante del preprocesador

La expresión que sigue a #if o #elif debe expandirse a

Las constantes de caracteres, cuando se evalúan en #if -expressions, pueden interpretarse en el juego de caracteres fuente, el juego de caracteres de ejecución, o algún otro juego de caracteres definido por la implementación.

La aritmética entera en expresiones #if se realiza utilizando la semántica de intmax_t para tipos con signo y uintmax_t para tipos sin signo.

(desde C99)

Expresión constante entera

Una expresión constante entera es una expresión que consiste únicamente de

  • _Alignof (hasta C23) alignas (desde C23) operadores
(desde C11)
  • constantes literales nombradas y compuestas que son de tipo entero o que son de tipo aritmético y son los operandos inmediatos de conversiones
(desde C23)

Las expresiones constantes enteras se evalúan en tiempo de compilación. Los siguientes contextos requieren expresiones que se conocen como expresiones constantes enteras :

(desde C99)
(desde C11)
  • El número de bits N de un tipo entero de precisión de bits ( _BitInt ( N ) )
(desde C23)

Inicializador estático

Las expresiones que se utilizan en los inicializadores de objetos con duración de almacenamiento static y thread_local o declarados con el especificador de clase de almacenamiento constexpr (desde C23) deben ser literales de cadena o expresiones que pueden ser una de las siguientes

1) expresión constante aritmética , que es una expresión de cualquier tipo aritmético que consiste en
(desde C11)
  • constantes literales nombradas o compuestas de tipo aritmético
(desde C23)
2) una constante de puntero nulo (por ejemplo, NULL ).
3) expresión constante de dirección , que es
  • usando el operador unario de dirección
  • convirtiendo una constante entera a un puntero
  • mediante conversión implícita conversión de array-a-puntero o función-a-puntero.
4) expresión constante de dirección de algún tipo de objeto completo, más o menos una expresión constante entera .
5) una constante con nombre que es, un identificador que es
  • una constante de enumeración
  • una constante predefinida (una de true , false o nullptr )
  • declarado con el especificador de clase de almacenamiento constexpr y tiene un tipo objeto
o una expresión postfija que aplica el operador de acceso a miembro . a una constante con nombre de tipo estructura o unión, incluso recursivamente.
6) una constante de literal compuesto , que es
  • un literal compuesto con el especificador de clase de almacenamiento constexpr
  • una expresión postfija que aplica el operador de acceso a miembro . a una constante de literal compuesto de tipo estructura o unión, incluso recursivamente.

Una constante de estructura o unión es una constante con nombre o constante de literal compuesto con tipo estructura o unión, respectivamente. Si el operador de acceso a miembro . accede a un miembro de una constante de unión, el miembro accedido debe ser el mismo que el miembro que es inicializado por el inicializador de la constante de unión.

(desde C23)
7) expresión constante de una de las otras formas aceptadas por la implementación.

A diferencia de las expresiones constantes enteras, las expresiones de inicializador estático no requieren ser evaluadas en tiempo de compilación; el compilador tiene la libertad de convertir dichos inicializadores en código ejecutable que se invoca antes del inicio del programa.

static int i = 2 || 1 / 0; // inicializa i al valor 1

El valor de un inicializador estático de punto flotante nunca es menos preciso que el valor de la misma expresión ejecutada en tiempo de ejecución, pero puede ser mejor.

Expresiones constantes de punto flotante

Las expresiones constantes aritméticas de tipos de punto flotante que no se utilizan en inicializadores estáticos siempre se evalúan como si fuera durante el tiempo de ejecución y se ven afectadas por el redondeo actual (si FENV_ACCESS está activado) y reportan errores como se especifica en math_errhandling .

void f(void)
{
#pragma STDC FENV_ACCESS ON
    static float x = 0.0 / 0.0; // inicializador estático: no genera una excepción
    float w[] = { 0.0 / 0.0 };  // genera una excepción
    float y = 0.0 / 0.0;        // genera una excepción
    double z = 0.0 / 0.0;       // genera una excepción
}

Notas

Si una expresión se evalúa a un valor que no es representable por su tipo, no puede utilizarse como expresión constante.

Las implementaciones pueden aceptar otras formas de expresiones constantes. Sin embargo, estas expresiones constantes no se consideran expresiones constantes enteras, expresiones constantes aritméticas o expresiones constantes de dirección, y por lo tanto no pueden utilizarse en contextos que requieran estos tipos de expresiones constantes. Por ejemplo, int arr [ ( int ) + 1.0 ] ; declara un VLA.

Referencias

  • Estándar C23 (ISO/IEC 9899:2024):
  • 6.6 Expresiones constantes (p: 95-96)
  • Estándar C17 (ISO/IEC 9899:2018):
  • 6.6 Expresiones constantes (p: 76-77)
  • Estándar C11 (ISO/IEC 9899:2011):
  • 6.6 Expresiones constantes (p: 106-107)
  • Estándar C99 (ISO/IEC 9899:1999):
  • 6.6 Expresiones constantes (p: 95-96)
  • Estándar C89/C90 (ISO/IEC 9899:1990):
  • 3.4 EXPRESIONES CONSTANTES

Véase también

Documentación de C++ para Expresiones constantes