rotacion operadores manipulacion logicos complemento bitwise c++ c bitwise-operators

c++ - manipulacion - operadores logicos



¿Se definen los resultados de las operaciones bit a bit en los enteros con signo? (4)

Sé que el comportamiento de >> en el entero con signo puede depender de la implementación (específicamente, cuando el operando de la izquierda es negativo).

¿Qué pasa con los demás: ~ , >> , & , ^ , | ? Cuando sus operandos están firmados con enteros de tipo incorporado ( short , long , long , long long ), ¿se garantiza que los resultados serán los mismos (en términos de contenido de bits) como si su tipo no estuviera firmado?


El contenido del bit será el mismo, pero los valores resultantes seguirán dependiendo de la implementación.

Realmente no debería ver los valores como firmados o sin firmar cuando se usan operaciones bit a bit, porque eso está funcionando en un nivel diferente.

El uso de tipos sin firmar te salva de algunos de estos problemas.


El estándar C89 definió el comportamiento de los números con signo de desplazamiento a la izquierda en función de las posiciones de los bits. Si ni los tipos firmados ni los no firmados tienen bits de relleno, el comportamiento requerido para los tipos sin firmar, combinado con el requisito de que los tipos firmados positivos compartan la misma representación que los tipos sin signo, implicaría que el bit de signo está inmediatamente a la izquierda del bit de valor más significativo .

Esto, en C89, -1 << 1 sería -2 en implementaciones de complemento de dos que no tienen bits de relleno y -3 en las de complemento de las implementaciones que no tienen bits de relleno. Si hay implementaciones de magnitud de signo sin bits de relleno, -1 << 1 sería igual a 2 en esos.

El Estándar C99 cambió los cambios a la izquierda de los valores negativos a Comportamiento Indefinido, pero nada en el fundamento da ninguna pista de por qué (o incluso menciona el cambio en absoluto). El comportamiento requerido por C89 puede haber sido menos que ideal en algunas implementaciones de complemento, por lo que tendría sentido permitir a esas implementaciones la libertad de seleccionar algo mejor. No he visto ninguna evidencia que sugiera que los autores del Estándar no pretendían que las implementaciones de calidad de dos complementos siguieran proporcionando el mismo comportamiento exigido por C89, pero desafortunadamente no lo dijeron.


Para los operandos negativos, << tiene un comportamiento indefinido y el resultado de >> está definido por la implementación (generalmente como desplazamiento de la derecha "aritmética"). << y >> son conceptualmente operadores no bit a bit. Son operadores aritméticos equivalentes a la multiplicación o división por la potencia apropiada de dos para los operandos en los que están bien definidos.

En cuanto a los operadores bit a bit genuinos ^ , ~ , | y & , operan en la representación de bit del valor en el tipo (posiblemente promovido) del operando. Sus resultados están bien definidos para cada posible elección de representación firmada (complemento de dos, complemento de uno o magnitud de signo), pero en los dos últimos casos es posible que el resultado sea una representación de trampa si la implementación trata el "cero negativo" representación como una trampa. Personalmente, casi siempre uso expresiones sin signo con operadores bit a bit para que el resultado esté 100% bien definido en términos de valores en lugar de representaciones .

Finalmente, tenga en cuenta que esta respuesta tal como está escrita solo puede aplicarse a C. C y C ++ son idiomas muy diferentes y aunque no conozco bien C ++, entiendo que puede diferir en algunas de estas áreas de C ...


  • Un desplazamiento a la izquierda << de un valor negativo tiene un comportamiento indefinido;
  • Un desplazamiento a la derecha >> de un valor negativo proporciona un resultado definido por la implementación;
  • El resultado de la & , | y ^ operadores se define en términos de la representación bit a bit de los valores. Se permiten tres posibilidades para la representación de números negativos en C: complemento de dos, complemento de uno y magnitud de signo. El método utilizado por la implementación determinará el resultado numérico cuando estos operadores se usen en valores negativos.

Obsérvese que el valor con el bit de signo 1 y todos los bits de valor cero (para el complemento de dos y magnitud de signo), o con el bit de signo y todos los bits de valor 1 (para el complemento de uno) está explícitamente permitido representar una trampa , y en este Si usa argumentos para estos operadores que generarían dicho valor, el comportamiento no está definido.