2009-07-30 7 views
0

Imaginez que j'ai les variables suivantes:entiers de la carte, short et char bitpattern

unsigned long a = 1; //32-bit value 
unsigned short b = 1; //16-bit value 
unsigned char c ='\x01' //8-bit value 

unsigned char buffer[7]; 

Je souhaite carte ou combiner ces variables ci-dessus dans le tampon comme suit: quatre premiers octets doivent être occupés par la valeur de int a, les 2 octets suivants par la valeur b et le dernier octet par c.

==> buffer = 0x 00000001 0001 01 

Est-ce que quelqu'un ici est au courant d'un moyen facile de le faire en C++? En ce moment j'ai une fonction d'aide qui retourne le modèle d'octets pour les shorts et les entiers mais je suppose qu'en C++ il doit y avoir une meilleure façon de faire ça?

Merci

+0

Il suffit de garder à l'esprit que vous ne pouvez pas faire de telles hypothèses portably sur les tailles de « court » et « long » –

Répondre

2
*(unsigned long*)(buffer+0) = a; 
*(unsigned short*)(buffer+4) = b; 
*(unsigned char*)(buffer+6) = c; 

Notez cependant que sur certaines architectures CPU (mais pas x86), cela ne fonctionne pas en raison de problèmes d'alignement. Sur x86, cela entraînera une certaine inefficacité dans les transactions de mémoire.

0

Il est en désordre, mais:

Entrant dans le tampon

buffer[ 0 ] = (unsigned char) a; 
buffer[ 1 ] = (unsigned char)(a >> 8); 
buffer[ 2 ] = (unsigned char)(a >> 16); 
buffer[ 3 ] = (unsigned char)(a >> 24); 
buffer[ 4 ] = (unsigned char) b; 
buffer[ 5 ] = (unsigned char)(b >> 8); 
buffer[ 6 ] = c; 

En sortant de tampon

a = buffer[ 0 ] | (buffer[ 1 ] << 8) | (buffer[ 2 ] << 16) | (buffer[ 3 ] << 24); 
b = buffer[ 4 ] | (buffer[ 5 ] << 8); 
c = buffer[ 6 ]; 
4

Utilisez un syndicat

#include <iostream> 
struct MyStructData 
{ 
    unsigned long a; 
    unsigned short b; 
    unsigned char c; 
}; 
union Swap 
{ 
    MyStructData data; 
    char   buffer[7];// Can use [sizeof(MyStructData)] 
}; 

int main() 
{ 
    Swap data; 
    data.data.a = 1; 
    data.data.b = 1; 
    data.data.c = 1; 

    for(int loop=0;loop < 7;++loop) 
    { 
     std::cout << "buffer(" << loop <<") = (" << (int)data.buffer[loop] << ")\n"; 
    } 
} 
+0

+1 pour avoir lu dans mes pensées. –

+1

#pragma pack, quelqu'un? – EFraim

+1

+1, mais j'utiliserais aussi "#pragma pack (1)" comme indiqué ci-dessus – gatorfax

1

en plus des autres réponses (qui a l'air bien), vous pouvez le faire comme ceci (note selon l'arc, vous devrez peut-être réorganiser le contenu de la structure. vous pouvez également activer l'emballage pour assurer qu'aucun remplissage est inséré entre les membres):

union { 
    struct { 
     int int_value; 
     short short_value; 
     char char_value; 
    } values; 
    char buffer[sizeof(values)]; 
} x; 

x.values.int_value = a; 
x.values.short_value = b; 
x.values.char_value = c; 
+0

En règle générale, vous devez activer l'emballage. Presque toutes les architectures actuelles sont alignées au moins sur 32 bits. Et BTW, au moins dans VC++, en mettant l'int_value en premier, forcera l'alignement de 32 bits pour tous les membres de la structure. – EFraim

+0

@EFrain: Tout simplement pas vrai car il s'aligne correctement sans conseils sur ma machine. Si l'ordre était inversé, je soupçonnerais qu'il ne serait pas emballé correctement en raison de problèmes d'alignement. –

+1

@Marfin: Oui, avec int_value, il pourrait d'abord s'aligner correctement sur VC++. Pas sur GCC. Le point est que, lorsqu'il est inversé, il ne sera pas aligné même sur VC++. Ainsi, vous ne pouvez pas faire confiance à cette solution sans pack. – EFraim

Questions connexes