usar - error function c
¿Cómo es posible que un operador unario+/- cause una promoción integral en "-a" o "+ a", siendo "a" un tipo de datos aritméticos constante/variable? (4)
Durante las operaciones con operadores binarios, se realiza la promoción aritmética a la forma más alta que se necesita, desde int a long, float o double.
double c=2+3.5
Pero en operadores unarios +
, -
solo se permiten promociones en tipos de datos de tipo Entero. De corto a int o largo.
unsigned char a=255;
cout<<sizeof(a)<<endl; //prints 1
cout<<sizeof(+a)<<endl; //prints 4
cout<<sizeof(++a)<<endl; //prints 1
Entonces, estas promesas integrales no funcionan en otros operadores unarios ++a
y a++
Esta línea aparentemente trivial está tomada del libro C mi Mike Banahan & Brady (Sección 2.8.8.2) .
Puedo entender cómo la promoción implícita entra en juego en expresiones como c=a+b
dependiendo de los tipos de operandos, pero no puedo entender cómo y en qué caso lo mismo puede figurar en algo como -b
, donde b es cualquier operando legítimo. ¿Puedes explicarlo y luego dar un buen ejemplo?
El texto extraído sigue:
Las conversiones aritméticas habituales se aplican a ambos operandos de las formas binarias de los operadores. Solo las promociones integrales se realizan en los operandos de las formas unarias de los operadores.
Actualizar:
Para que pase desapercibido, aquí estoy agregando lo que pregunté basado en la respuesta de OUAH en un comentario- El libro dice '' Only the integral promotions are performed
las Only the integral promotions are performed
'' ... ¿Significa eso en una expresión como x=-y
, donde ''x ''es un doble largo y'' y ''es un flotante,'' y ''no se promocionará a double largo si utilizamos explícitamente un operador unario? Sé que sería, pero pidiéndole, sin embargo, tener una idea más clara sobre la parte "Solo las promociones intelectuales ...".
Actualizar:
¿Puede explicar con un ejemplo cómo entra en juego la promoción para los siguientes operadores bit-wise? Para los últimos tres, ¿debería suponer que cada vez que se usan en una variable, primero se promueve a tipo entero? ¿Y qué significa exactamente las "conversiones aritméticas habituales" para los primeros tres? ¿Puedes dar un pequeño ejemplo? No quiero publicarlo como una pregunta separada si se puede resolver aquí.
No estoy seguro, pero creo que cada operación se promueve a un tipo adecuado. Primero se realiza la conversión y, en segundo lugar, se finaliza la operación. La operación -b
cambia el valor de la variable de resultado, por lo que la promoción debe realizarse y luego se convierte el signo de valor.
Las operaciones como +b
también son operaciones, por lo que hay un proceso de Promoción + Operación. No sé si una optimización de código podría omitir este proceso en este caso concreto.
Para un operador aritmético unario, el estándar C dice (en la sección 6.5.3.3) que
Las promociones enteras se realizan en el operando y el resultado tiene el tipo promocionado.
También define el término, en la sección 6.3.1.1:
Si un
int
puede representar todos los valores del tipo original (como está restringido por el ancho, para un campo de bit), el valor se convierte en unint
; de lo contrario, se convierte aunsigned int
. Estas se llaman promociones enteras . Todos los otros tipos no se modifican por las promociones enteras.
(Las referencias corresponden al borrador N1570 del estándar C de 2011).
Creo que la razón de esto es que las implementaciones no son necesarias para admitir operaciones aritméticas en tipos más estrechos que int
(una "palabra"). Los operandos más estrechos que un int
se convierten a int
, o a unsigned int
, antes de que se operen.
Para operadores binarios (aquellos que toman dos operandos), existe un requisito adicional, que ambos operandos deben ser del mismo tipo. Las CPU típicas pueden tener instrucciones para agregar dos enteros con signo de 32 bits, o dos enteros sin signo de 32 bits, o dos enteros con signo o sin signo de 64 bits, pero ninguno agregará directamente, por ejemplo, un entero con signo de 32 bits y un Entero sin signo de 64 bits. Para permitir esto, tenemos las conversiones aritméticas habituales , que se describen en la sección 6.3.1.8. Estas reglas le indican, por ejemplo, qué sucede cuando intenta agregar un int
a un double
: el operando int
se promueve, mediante conversión, para que escriba " double
, y la suma agrega los dos operandos double
resultantes.
Los operadores de turno no requieren las conversiones aritméticas habituales , ya que no es necesario que ambos operandos sean del mismo tipo. El operando de la izquierda es un valor para ser operado; el operando derecho especifica el número de bits para desplazarlo.
¿Significa que en una expresión como
x=-y
, dondex
es unlong double
ey
es unfloat
,y
no se promoverá along double
si usamos explícitamente un operadorunary
?
La asignación hace que el operando derecho se convierta al tipo del operando izquierdo. La expresión -y
se evalúa independientemente del contexto en el que aparece (esto es cierto para la mayoría de las expresiones). Entonces unary -
se aplica a su operando, que es de tipo float
(las promociones enteras no afectan eso), produciendo un resultado de tipo float
. La asignación hace que ese valor float
se convierta en long double
antes de asignarse a x
.
El título de tu pregunta pregunta cómo puede suceder esto. No estoy seguro de lo que eso significa. Las reglas de conversión se especifican en el estándar de idioma. Los compiladores siguen esas reglas.
Tome este ejemplo en un sistema de 32 bits:
unsigned char a = 42;
printf("%zu/n", sizeof a); // prints 1
printf("%zu/n", sizeof +a); // prints 4, a has been promoted to int