web-dev-qa-db-fra.com

Conversion d'octets en Int/uint en C

J'ai un tableau de caractères non signé [248]; rempli d'octets. Comme 2F AF FF 00 EB AB CD EF ..... Ce tableau est mon flux d'octets dans lequel je stocke mes données de UART (RS232) en tant que tampon.

Maintenant, je veux reconvertir les octets en uint16 et int32.

En C #, j'ai utilisé la classe BitConverter pour le faire. par exemple:

byte[] Array = { 0A, AB, CD, 25 };
int myint1 = BitConverter.ToInt32(bytes, 0);
int myint2 = BitConverter.ToInt32(bytes, 4);
int myint3 = BitConverter.ToInt32(bytes, 8);
int myint4 = BitConverter.ToInt32(bytes, 12);
//...
enter code here
Console.WriteLine("int: {0}", myint1); //output Data...

Existe-t-il une fonction similaire en C? (non .net, j'utilise le compilateur KEIL car le code est exécuté sur un microcontrôleur) 

Cordialement Sam

10
Sam

Oui il y a. Supposons que vos octets sont dans:

uint8_t bytes[N] = { /* whatever */ };

Nous savons qu’un entier de 16 bits est constitué de deux entiers de 8 bits concaténés, c’est-à-dire qu’un a un multiple de 256 ou est décalé de 8:

uint16_t sixteen[N/2];

for (i = 0; i < N; i += 2)
    sixteen[i/2] = bytes[i] | (uint16_t)bytes[i+1] << 8;
             // assuming you have read your bytes little-endian

De même pour 32 bits:

uint32_t thirty_two[N/4];

for (i = 0; i < N; i += 4)
    thirty_two[i/4] = bytes[i] | (uint32_t)bytes[i+1] << 8
        | (uint32_t)bytes[i+2] << 16 | (uint32_t)bytes[i+3] << 24;
             // same assumption

Si les octets sont lus big-endian, vous inversez évidemment l'ordre:

bytes[i+1] | (uint16_t)bytes[i] << 8

et

bytes[i+3] | (uint32_t)bytes[i+2] << 8
    | (uint32_t)bytes[i+1] << 16 | (uint32_t)bytes[i] << 24

Notez qu’il existe une différence entre l’endian-ness dans l’entier stocké et l’endian-ness de l’architecture en cours. La finalité à laquelle il est fait référence dans cette réponse est du nombre entier stocké, c'est-à-dire le contenu de bytes. Les solutions sont indépendantes de l’endicité de l’architecture en cours d’exécution puisque l’endianisme est pris en charge lors du déplacement .

10
Shahbaz

Il n'y a pas de fonction standard pour le faire pour vous en C. Vous devrez rassembler vous-même les octets dans vos entiers 16 et 32 ​​bits. Attention à l'endianité!

Voici un exemple simple de petit boutien:

extern uint8_t *bytes;
uint32_t myInt1 = bytes[0] + (bytes[1] << 8) + (bytes[2] << 16) + (bytes[3] << 24);

Pour un système big-endian, c'est juste l'inverse:

uint32_t myInt1 = (bytes[0] << 24) + (bytes[1] << 16) + (bytes[2] << 8) + bytes[3];

Vous pourriez peut-être vous en tirer avec:

uint32_t myInt1 = *(uint32_t *)bytes;

Si vous faites attention aux problèmes d'alignement.

17
Carl Norum
            char letter = 'A';
            size_t filter = letter;
            filter = (filter <<  8 | filter);
            filter = (filter << 16 | filter);
            filter = (filter << 32 | filter);
            printf("filter: %#I64x \n", filter); 

résultat: "filtre: 0x4141414141414141"

0
Andre

En cas de petit boutien, ne pouvez-vous pas simplement utiliser memcpy?

memcpy((char*)&myint1, aesData.inputData[startindex], length);
0
Sven Depoorter