2010-04-30 11 views
7

Tengo una variable de 32 bits de longitud, CurrentPosition, que quiero dividir en 4 caracteres de 8 bits. ¿Cómo haría eso de la manera más eficiente en C? Estoy trabajando con una MCU de 8 bits, arquitectura 8051.¿Cómo se divide un valor largo (32 bits) en cuatro variables de caracteres (8 bits) usando C?

unsigned long CurrentPosition = 7654321; 
unsigned char CP1 = 0; 
unsigned char CP2 = 0; 
unsigned char CP3 = 0; 
unsigned char CP4 = 0; 
// What do I do next? 

¿Debo hacer referencia a la dirección inicial de CurrentPosition con un puntero y luego añadir 8 dos que aborda cuatro veces?

Es pequeño Endian.

TAMBIÉN quiero que CurrentPosition se mantenga sin cambios.

+2

¿Qué endian? ___ – kennytm

+0

Estoy usando SDCC con el formato Little Endian – PICyourBrain

Respuesta

13
CP1 = (CurrentPosition & 0xff000000UL) >> 24; 
    CP2 = (CurrentPosition & 0x00ff0000UL) >> 16; 
    CP3 = (CurrentPosition & 0x0000ff00UL) >> 8; 
    CP4 = (CurrentPosition & 0x000000ffUL)  ; 

Usted puede acceder a los bytes a través de un puntero, así,

unsigned char *p = (unsigned char*)&CurrentPosition; 
//use p[0],p[1],p[2],p[3] to access the bytes. 
+0

1) ¿Necesito echar estos con (char sin signo)? 2) ¿Esto no afecta a CurrentPosition? – PICyourBrain

+1

1. El primero necesitará conversión 2. Ambos métodos no afectan a CurrentPosition – Saul

+0

El primero no * necesita * conversión, pero algunos compiladores darán una advertencia falsa sobre una posible pérdida de precisión si no lo hace. – caf

0
CP1 = (unsigned char)(CurrentPosition & 0xFF); 
CurrentPosition >>= 8; 
CP2 = (unsigned char)(CurrentPosition & 0xFF); 
... 
+0

Esto cambiaría el valor en CurrentPosition ¿verdad? Quiero dejar CurrentPosition sin cambios. – PICyourBrain

+0

Sí, una opción es hacer una copia de CurrentPosition y modificar la copia. O la respuesta de nos es otra opción. Tu idea de usar un puntero también es posible.Hay muchas formas de hacer esto. –

2

si está utilizando una MCU de 8 bits cambiando toda una variable de 32 bits es un poco de trabajo. En este caso, es mejor leer 4 bytes de CurrentPosition usando la aritmética del puntero. El reparto:

unsigned char *p = (unsigned char*)&CurrentPosition; 

no cambia el CurrentPosition, pero si intenta escribir en p [0] cambiará el byte menos significativo de la CurrentPosition. Si desea una copia, haga lo siguiente:

unsigned char *p = (unsigned char*)&CurrentPosition; 
unsigned char arr[4]; 
arr[0] = p[0]; 
arr[1] = p[1]; 
arr[2] = p[2]; 
arr[3] = p[3]; 

y trabaje con arr. (Si desea el byte más significativo, primero cambie el orden en esas asignaciones).

Si usted prefiere 4 variables Puede obviamente hacer:

unsigned char CP1 = p[0]; 
unsigned char CP2 = p[1]; 
unsigned char CP3 = p[2]; 
unsigned char CP4 = p[3]; 
+0

Esta solución es mejor si no puede cambiar un int de 32 bits directamente. –

5

creo que usted debe considerar el uso de un sindicato:

union { 
    unsigned long position; 
    unsigned char bytes[4]; 
} CurrentPosition; 

CurrentPosition.position = 7654321; 

Los bytes se puede acceder ahora como: CurrentPosition.bytes [0 ], ..., CurrentPosition.bytes [3]

+0

Una buena idea en la práctica porque el compilador puede hacer la descomposición del int en bytes. Una mala idea en teoría porque este uso de las uniones no está definido por el estándar c. (La mayoría, si no todas las implementaciones funcionarán) –

+0

@Nils El tipo de juego de palabras con uniones ha sido bien definido desde C99. Sin embargo, el código aún es endian dependiente. – user694733

0
unsigned char *CP = &CurrentPosition; 

Ahora CPN por el código original se accede a través CP[n].

0

Sé que esto fue publicado hace un tiempo. Pero para cualquiera que siga leyendo el hilo: Muchas personas adoptan el enfoque de cambiar secuencialmente el valor original. ¿Por qué no dejas que el compilador haga el trabajo por ti? Use una unión & para permitirle almacenar los valores en la misma ubicación. Defina una unión que consta de una variable larga de 32 bits (aquí será donde guarda su CurrentPosition) y una estructura que consta de 4 variables char. O simplemente un simple conjunto de enteros de 8 bits. Cuando escriba su CurrentPosition en la variable larga, se almacenará en la misma ubicación a la que accedió cuando lea las 4 variables de char. Este método es mucho menos laborioso y no permite que el compilador haga el trabajo en lugar de perder recursos de tiempo &.

+1

Eso es exactamente lo que sugiere [la segunda respuesta más votada] (https://stackoverflow.com/a/2747324/2564301). – usr2564301

Cuestiones relacionadas