2012-10-12 46 views
5

Estoy tratando de convertir una enumeración de código C++ a código C#, y estoy teniendo problemas para entenderlo. El código C++ es:Reproducción de código de desplazamiento de bit de C++ a C#

enum FOO { 
    FOO_1 = 0, 
    FOO_2, 
    // etc 
} 

#define MASK(x) ((1 << 16) | (x)) 

enum DISP 
{ 
    DISP_1 = MASK(FOO_1), 
    DISP_2 = MASK(FOO_2), 
    // etc 
} 

Lo que no entiendo es lo MÁSCARA está haciendo, y cómo puede emular la funcionalidad en C#, o entender lo que está haciendo y establecer el DISP enumeración manualmente sin ella.

No estoy seguro de lo que estoy diciendo tiene sentido, pero eso es de esperar cuando no estoy del todo seguro de lo que estoy viendo.

+0

Debe leer acerca de cambios (<<) y o (|) los operadores en C++ para que pueda entender lo que está pasando. – coredump

+0

¡Definitivamente lo haré! – Wint

Respuesta

5

MASK(x) construye un número por OR -ing en una serie x con un número binario 10000000000000000 (uno movido a la izquierda 16 veces).

En C# se puede utilizar una expresión directamente como aquí:

enum FOO { 
    FOO_1 = 0, 
    FOO_2, 
    // etc 
} 

enum DISP 
{ 
    DISP_1 = (1<<16) | (int)(FOO.FOO_1), 
    DISP_2 = (1<<16) | (int)(FOO.FOO_2), 
    // etc 
} 
+0

Esto es exactamente lo que estaba buscando. ¡Gracias por el ejemplo! – Wint

2

Basta con sustituir MASK con lo que se define como (existen los << y | operadores en C# también):

enum DISP 
{ 
    DISP_1 = ((1 << 16) | FOO.FOO_1), 
    DISP_2 = ((1 << 16) | FOO.FOO_2) 
} 

Si usted se está preguntando exactamente lo que el turno y u operadores lo hacen, usted' tomando el valor binario de 0000000000000001 y lo desplaza 16 valores a la izquierda: 1000000000000000.

Otro ejemplo, (000001101 << 3) se convierte en 001101000.

el operador OR toma todos los valores 1 a partir de cualquiera de los operandos y define el valor del resultado a 1.

Por ejemplo, 0001 | 0110 se convierte 0111.

Así pues, tomar DISP_2:

(0b00000000000000001 << 16) | 0b00000000000000010) 
= (0b10000000000000000 | 0b00000000000000010) 
= (0b10000000000000010) 
= 65538 

(sé el formato 0b no funciona en C# y no es estándar en C, pero es más útil el uso de la notación binaria en lugar de hexadecimal, más fácil para ver lo que los operadores están haciendo)

7

cuando poco cambio, cambia todos los de la 1 y 0 a la izquierda oa la derecha de un número determinado de valores.

en su caso 1 << 16 crea 10000000000000000 en binario. (Sí, eso es 16 ceros).

Luego toma ese número y usa | que es el operador bit a bit. por lo tanto, sea cual sea el valor entero de la enumeración, se transfiere en bits a ese número que cambiamos de bit.

Si, por ejemplo, usa MASK(FOO_4) (que tiene el valor literal de 3) 3 es 11 en binario, por lo que el resultado sería 10000000000000011. Esto es funcionalmente lo mismo que agregar 65,536 a cada valor.

Ahora, cuando declaramos la segunda enumeración, estamos estableciendo los valores de esos valores enum para esta extraña función de enmascaramiento.

Para hacer lo mismo en C# Prueba esto:

enum Foo { //this may not be needed anymore? 
    FOO_1 = 0, FOO_2, ... etc 
} 

enum Disp { //DISP_2 gets the next value ie 65536 + 1, and so forth 
    DISP_1 = 65536, DISP_2, DISP_3, ... etc 
+1

No necesita el + 1, + 2, etc., el resto se asignará secuencialmente desde el especificado al inicio. DISP_1 es el único que necesita un valor explícito asignado (y FOO_1 ni siquiera necesita ser especificado ya que comienza en 0). – jrajav

+0

Buena llamada, tienes razón. Me olvide de eso. Al igual que PHP – ohmusama

+0

"Al igual que C/C++" es probablemente más relevante;) – jrajav

0

Los valores numéricos que DISP_x son iguales:

DISP_1 == 0x10000 
DISP_2 == 0x10001 
DISP_3 == 0x10002 
... 
0

El operador de desplazamiento de bits funciona en C#, pero la definen macro doesn' t.

Para entender lo que está pasando, puede hacer es calcular los valores por separado y luego ponerlos en la enumeración.

Por supuesto que usted sabe que | es el operador O bit a bit. Y en caso de que el operador << hace es cambiar el binario a la izquierda:

1 << 16 = 10000000000000000_2 //those are 16 zeroes and _2 indicates binary 

A su vez:

10000000000000000_2 = 65536 

Esa es la quivalent de mutiplying el número por 2 el número de veces indicado por el segundo operando

1 << 1 = 2 
1 << 2 = 4 
1 << 3 = 8 

Eso es correcto, es multiplicar el número por una potencia de dos:

1 << 1 <=> 1 * 2^1 = 2 
1 << 2 <=> 1 * 2^2 = 4 
1 << 3 <=> 1 * 2^3 = 8 

ahora, ya FOO_1 = 0 continuación

DISP_1 = MASK(FOO_1) 
=> 
DISP_1 = ((1 << 16) | (FOO_1)) 
=> 
DISP_1 = (65536 | (FOO_1)) 
=> 
DISP_1 = (65536 | FOO_1) 
=> 
DISP_1 = (65536 | 0) 
=> 
DISP_1 = 65536 

Hacer lo mismo para FOO_2 que tomo tiene la el valor 1 le dará:

DISP_2 = (65536 | FOO_2) 
=> 
DISP_2 = (65536 | 1) 
=> 
DISP_2 = 65537 

Dicho esto correctamente las siguientes obras:

enum FOO 
{ 
    FOO_1 = 0, 
    FOO_2, 
    // etc 
} 

enum DISP 
{ 
    DISP_1 = (1<<16) | (int)(FOO.FOO_1), 
    DISP_2 = (1<<16) | (int)(FOO.FOO_2), 
    // etc 
} 
Cuestiones relacionadas