operadores - ¿Cuál es la diferencia entre asignar directamente el resultado de la operación de desplazamiento a la izquierda a una variable y la operación de asignación de desplazamiento a la izquierda en C?
operadores logicos en pic c (3)
En la siguiente expresión, el resultado de la operación de desplazamiento a la izquierda se asigna a la variable i
.
int i;
i = 7 << 32;
printf("i = %d/n",i);
En la siguiente expresión, se lleva a cabo la operación de asignación de desplazamiento a la izquierda.
int x = 7;
x <<= 32;
printf("x = %d/n",x);
Ambas expresiones anteriores dieron resultados diferentes. Pero no es lo mismo con las siguientes dos expresiones. Ambos dieron el mismo resultado. Entonces, ¿cuál podría ser la razón de que las expresiones anteriores devuelvan valores diferentes?
int a;
a = 1 + 1;
printf("a = %d/n",a);
int b = 1;
b += 1;
printf("b = %d/n",b);
Estoy de acuerdo con los comentarios de Cody Gray . Solo para las personas en el futuro que terminen aquí, la manera de resolver esta ambigüedad es usar sin firmar durante mucho tiempo.
unsigned long long int b = 7ULL<<32; // ULL here is important, as it tells the compiler that the number being shifted is more than 32bit.
unsigned long long int a = 7;
a <<=32;
La semántica operacional abstracta de ISO/IEC 9899
dice:
6.5.7 Bitwise shift operators --- Semantics
3 .... .... Si el valor del operando derecho es negativo o es mayor o igual que el ancho del operando izquierdo promovido, el comportamiento no está definido.
En su caso, desmontando y viendo lo que sucede, vemos así:
[root@arch stub]# objdump -d a.out | sed ''/ <main>/,/^$/ !d''
00000000004004f6 <main>:
4004f6: 55 push %rbp
4004f7: 48 89 e5 mov %rsp,%rbp
4004fa: 48 83 ec 10 sub $0x10,%rsp
4004fe: c7 45 fc 07 00 00 00 movl $0x7,-0x4(%rbp)
400505: b8 20 00 00 00 mov $0x20,%eax
40050a: 89 c1 mov %eax,%ecx
40050c: d3 65 fc shll %cl,-0x4(%rbp) <<== HERE IS THE PROBLEM
40050f: 8b 45 fc mov -0x4(%rbp),%eax
400512: 89 c6 mov %eax,%esi
400514: bf b4 05 40 00 mov $0x4005b4,%edi
400519: b8 00 00 00 00 mov $0x0,%eax
40051e: e8 cd fe ff ff callq 4003f0 <printf@plt>
400523: b8 00 00 00 00 mov $0x0,%eax
400528: c9 leaveq
400529: c3 retq
40052a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
El código generado intenta cambiar, pero el shll %cl,-0x4(%rbp)
(desplazamiento a la izquierda de un largo) no tiene ningún efecto.
El undefined behaviour
en este caso se encuentra en el ensamblaje, es decir, en la operación SHL.
El estándar C dice:
El resultado no está definido si el operando derecho es negativo, o mayor o igual que el número de bits en el tipo de expresión izquierda.
Por lo tanto, es un comportamiento indefinido porque int
normalmente tiene un tamaño de 32
bits, lo que significa que solo de 0
a 31
pasos están bien definidos .