La adición de dos caracteres produce int
-
25-10-2019 - |
Pregunta
Hice un programa simple y lo compilé con GCC 4.4/4.5 de la siguiente manera:
int main ()
{
char u = 10;
char x = 'x';
char i = u + x;
return 0;
}
G ++ -C -WConversion A.CPP
Y tengo lo siguiente:
a.cpp: In function ‘int main()’:
a.cpp:5:16: warning: conversion to ‘char’ from ‘int’ may alter its value
La misma advertencia que tengo para el siguiente código:
unsigned short u = 10;
unsigned short x = 0;
unsigned short i = u + x;
a.cpp: In function ‘int main()’:
a.cpp:5:16: warning: conversion to ‘short unsigned int’ from ‘int’ may alter its value
¿Alguien podría explicarme por qué la adición de dos caracteres (o dos pantalones cortos sin firmar) produce int? ¿Es un error del compilador o cumple con estándar?
Gracias.
Solución
Lo que está viendo es el resultado de las llamadas "conversiones aritméticas habituales" que ocurren durante las expresiones aritméticas, particularmente aquellas que son de naturaleza binaria (toman dos argumentos).
Esto se describe en §5/9:
Muchos operadores binarios que esperan operandos de aritmética o tipo de enumeración causan conversiones y tipos de resultados de rendimiento de manera similar. El propósito es producir un tipo común, que también es el tipo de resultado. Este patrón se llama el conversiones aritméticas habituales, que se definen de la siguiente manera:
- Si cualquiera de los operando es de tipo
long double
, el otro se convertirá enlong double
.
- De lo contrario, si cualquier operando esdouble
, el otro se convertirá endouble
.
- De lo contrario, si cualquier operando esfloat
, el otro se convertirá enfloat
.
- De lo contrario, las promociones integrales (4.5) se realizarán en ambos operandos.54)
- Entonces, si cualquier operando esunsigned long
el otro se convertirá enunsigned long
.
- De lo contrario, si un operando es unlong int
y el otrounsigned int
, entonces si unlong int
puede representar todos los valores de ununsigned int
, launsigned int
se convertirá a unlong int
; de lo contrario, ambos operandos se convertirán enunsigned long int
.
- De lo contrario, si cualquier operando eslong
, el otro se convertirá enlong
.
- De lo contrario, si cualquier operando esunsigned
, el otro se convertirá enunsigned
.Nota: de lo contrario, el único caso restante es que ambos operandos son
int
]
Las promociones aludidas en §4.5 son:
1 un rValue de tipo
char
,signed char
,unsigned char
,short int
, ounsigned short int
se puede convertir a un rValue de tipoint
siint
puede representar todos los valores del tipo de origen; De lo contrario, el rValue de origen se puede convertir en un rValue de tipounsigned int
.2 un rValue de tipo
wchar_t
(3.9.1) o un tipo de enumeración (7.2) puede convertirse en un rValue del primero de los siguientes tipos que pueden representar todos los valores de su tipo subyacente:int
,unsigned int
,long
, ounsigned long
.3 Un rValue para un campo de bits integral (9.6) se puede convertir en un rValue de tipo
int
siint
puede representar todos los valores del campo de bits; de lo contrario, se puede convertir aunsigned int
siunsigned int
puede representar todos los valores del campo de bits. Si el campo de bits es más grande aún, no se aplica una promoción integral. Si el campo de bits tiene un tipo enumerado, se trata como cualquier otro valor de ese tipo para fines de promoción.4 Un rValue de tipo
bool
se puede convertir a un rValue de tipoint
, confalse
convertirse en cero ytrue
convirtiéndoseone
.5 Estas conversiones se llaman promociones integrales.
Desde aquí, secciones como "Operadores multiplicativos" o "Operadores aditivos"Todos tienen la frase:"Las conversiones aritméticas habituales se realizan ..."Para especificar el tipo de expresión.
En otras palabras, cuando realiza aritmética integral, el tipo se determina con las categorías anteriores. En su caso, la promoción está cubierta por §4.5/1 y el tipo de expresiones son int
.
Otros consejos
Cuando realiza cualquier operación aritmética en char
tipo, el resultado que devuelve es de int
escribe.
Mira esto:
char c = 'A';
cout << sizeof(c) << endl;
cout << sizeof(+c) << endl;
cout << sizeof(-c) << endl;
cout << sizeof(c-c) << endl;
cout << sizeof(c+c) << endl;
Producción:
1
4
4
4
4
Demostración en ideona: http://www.ideone.com/jntmm
Cuando agregan estos dos personajes entre sí, primero están siendo promovidos a Int.
El resultado de una adición es un rValue que se promueve implícitamente para escribir INT si es necesario, y si un int puede contener el valor resultante. Esto es cierto en cualquier plataforma donde SIMEOF (INT)> SIMEOF (char). Pero tenga cuidado con el hecho de que Char podría ser tratado como firmado por su compilador.
Estos enlaces pueden ser de mayor ayuda - wiki y Securecoding