programacion operadores operador matematicos manipulacion logicos asignacion c bit-shift relational-operators

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 .