Pregunta

C define al menos 3 niveles de "expresión constante":

  • expresión constante (no calificada)
  • expresión constante aritmética
  • expresión constante entera

6.6 el párrafo 3 dice:

Las expresiones constantes no deberán contener la asignación, el incremento, la disminución, los operadores de funciones o la coma, excepto cuando están contenidos dentro de una subexpresión que no se evalúa.

¿Entonces esto significa 1,2 ¿No es una expresión constante?

El párrafo 8 dice:

Una expresión constante aritmética tendrá tipo aritmético y solo tendrá operandos que son constantes enteras, constantes flotantes, constantes de enumeración, constantes de caracteres y expresiones de tamaño.Los operadores de fundición en una expresión constante aritmética solo convertirán los tipos aritméticos en tipos aritméticos, excepto como parte de un operando a un operador de tamaño de tamaño cuyo resultado es una constante entera.

¿Cuáles son los operandos en (union { uint32_t i; float f; }){ 1 }.f?Si 1 es el operando, entonces presumiblemente se trata de una expresión constante aritmética, pero si { 1 } es el operando, entonces claramente no lo es.

Editar: Otra observación interesante:7.17 el párrafo 3 requiere el resultado de offsetof ser una expresión entera constante de tipo size_t, pero las implementaciones estándar de offsetof, hasta donde yo sé, el estándar no requiere que sean expresiones enteras constantes.Por supuesto, esto está bien ya que una implementación está permitida (según 6.6 párrafo 10) aceptar otras formas de expresiones constantes, o implementar la offsetof macro como __builtin_offsetof en lugar de mediante la resta de punteros.La esencia de esta observación, sin embargo, es que si quieres usar offsetof en un contexto donde se requiere una expresión constante entera, realmente necesita usar la macro proporcionada por la implementación y no utilizar la suya propia.

¿Fue útil?

Solución

Según tu lectura, 1,2 no es una expresión constante.No sé por qué no lo es, sólo que estoy de acuerdo contigo en que no lo es (a pesar de que probablemente debería serlo).

6.5.2 especifica literales compuestos como operador de sufijo.Entonces en

(union { uint32_t i; float f; }){ 1 }.f

Los operandos son (union { uint32_t i; float f; }){ 1 } y f hacia . operador.No es una expresión constante aritmética, ya que el primer argumento es una union tipo, pero es una expresión constante.

ACTUALIZAR: Me basé en una interpretación diferente de la norma.

Mi razonamiento anterior fue que (union { uint32_t i; float f; }){ 1 }.f cumplía los criterios para una expresión constante y, por lo tanto, era una expresión constante.Sigo pensando que cumple con los criterios para una expresión constante (6.6 párrafo 3), pero no es ninguno de los tipos estándar de expresiones constantes (entera, aritmética o dirección) y, por lo tanto, solo está sujeta a ser una expresión constante según el párrafo 6.6. 10, que permite expresiones constantes definidas por la implementación.

También tenía la intención de llegar a tu edición.Iba a argumentar que la implementación "pirateada" de offsetof Era una expresión constante, pero creo que es la misma que la anterior:cumple con los criterios para una expresión constante (y posiblemente una constante de dirección) pero no es una expresión constante entera y, por lo tanto, no es válida fuera del párrafo 10 de 6.6.

Otros consejos

Si 1,2 fuera una expresión constante, esto permitiría que un código como este se compilara:

{ // code        // How the compiler interprets:
  int a[10, 10]; // int a[10];

  a[5, 8] = 42;  // a[8] = 42;
}

No sé si es la verdadera razón, pero puedo imaginar que emitir un error por este (¿común?) error se consideró más importante que convertir 1,2 en una expresión constante.

ACTUALIZACIÓN : como R. señala en un comentario, el código sobre ya no es un error del compilador desde la introducción de los VLA.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top