Tipo de literales enteros no int por defecto?

Acabo de responder esta pregunta , que preguntaba por qué iterar hasta 10 mil millones en un bucle for toma mucho más tiempo (el OP en realidad lo abortó después de 10 minutos) que iterar hasta 1 mil millones:

for (i = 0; i < 10000000000; i++) 

Ahora mi respuesta obvia y la de muchos otros fue que se debió a que la variable de iteración era de 32 bits (que nunca alcanza los 10 mil millones) y el ciclo obtiene un ciclo infinito.

Pero aunque me di cuenta de este problema, todavía me pregunto qué estaba pasando realmente dentro del comstackdor.

Dado que el literal no se adjuntó con una L , en mi humilde opinión debería ser de tipo int , también, y por lo tanto de 32 bits. Por lo tanto, debido al desbordamiento, debe ser una int normal dentro del rango para ser alcanzable. Para reconocer realmente que no se puede acceder desde int , el comstackdor necesita saber que es 10 mil millones y, por lo tanto, verlo como una constante de más de 32 bits.

¿Se promueve dicho literal a un rango apropiado (o al menos definido por la implementación) (al menos 64 bits, en este caso) automáticamente, incluso si no se agrega una L y este comportamiento estándar? ¿O está sucediendo algo diferente detrás de escena, como UB debido a un desbordamiento (es un desbordamiento de enteros realmente UB)? Algunas citas del Estándar pueden ser agradables, si las hay.

Aunque la pregunta original era C, también aprecio las respuestas de C ++, si hay alguna diferente.

En lo que se refiere a C ++:

C ++ 11, [lex.icon] ¶2

El tipo de un entero literal es el primero de la lista correspondiente en la Tabla 6 en la que se puede representar su valor.

Y la Tabla 6, para literales sin sufijos y constantes decimales, da:

 int long int long long int 

(Curiosamente, para las constantes hexadecimales u octales también se permiten los tipos unsigned , pero cada uno viene después del correspondiente firmado en la lista)

Entonces, está claro que en ese caso la constante se ha interpretado como un long int (o long long int si long int era demasiado 32 bit).

Tenga en cuenta que “literales demasiado grandes” debería dar como resultado un error de comstackción:

Un progtwig está mal formado si una de sus unidades de traducción contiene un literal entero que no puede ser representado por ninguno de los tipos permitidos.

(ibidem, ¶3)

que se ve rápidamente en esta muestra , que nos recuerda que ideone.com usa comstackdores de 32 bits.


Ahora vi que la pregunta era sobre C … bueno, es más o menos lo mismo:

C99, §6.4.4.1

El tipo de una constante entera es la primera de la lista correspondiente en la que se puede representar su valor.

lista que es la misma que en el estándar de C ++.


Anexo: tanto C99 como C ++ 11 también permiten que los literales sean de “tipos enteros extendidos” (es decir, otros tipos enteros específicos de la implementación) si todo lo demás falla. (C ++ 11, [lex.icon] ¶3; C99, §6.4.4.1 ¶5 después de la tabla)

De mi borrador del estándar C etiquetado ISO / IEC 9899: Borrador del Comité TC2 – 6 de mayo de 2005 , las reglas son notablemente similares a las reglas de C ++ que Matteo encontró:

5 El tipo de una constante entera es la primera de la lista correspondiente en la que se puede representar su valor.

 Suffix Decimal Constant Octal or Hexadecimal Constant ------------------------------------------------------------------- none int int long int unsigned int long long int long int unsigned long int long long int unsigned long long int u or U unsigned int unsigned int unsigned long int unsigned long int unsigned long long int unsigned long long int l or L long int long int long long int unsigned long int long long int unsigned long long int Both u or U unsigned long int unsigned long int and l or L unsigned long long int unsigned long long int ll or LL long long int long long int unsigned long long int Both u or U unsigned long long int unsigned long long int and ll or LL 

Todavía me pregunto qué estaba pasando realmente dentro del comstackdor

Puede ver el ensamblador, si le interesa cómo el comstackdor interpreta el código.

10000000000:

 400054f: mov -0x4(%rbp),%eax mov %eax,-0x8(%rbp) addl $0x1,-0x4(%rbp) jmp 40054f  

por lo que simplemente compiló en bucle infinito, si reemplaza 10000000000 con 10000:

 .... test %al,%al jne 400551