2010-09-30 16 views
6

Ceci est un peu un suivi de this posting mais avec une question différente, je pensais que je devrais demander dans un thread séparé.Comment puis-je inverser l'ordre des octets d'un NSInteger ou NSUInteger dans l'objectif-c

Je suis au point où j'ai quatre octets consécutifs en mémoire que j'ai lus à partir d'un fichier. Je voudrais les stocker sous la forme d'un tableau de bits (la valeur int réelle de ces derniers n'a pas d'importance plus tard). Lorsque j'imprime ce qui est dans mon int, je remarque qu'il semble être stocké dans l'ordre inverse (little endian).

Est-ce que quelqu'un a une bonne méthode pour inverser l'ordre des octets. Puis, une fois inversé, choisir des bits consécutifs couvrant deux octets et la conversion à un int?

unsigned char data[] = { 0x00, 0x02, 0x45, 0x28 }; 
NSInteger intData = *((NSInteger *)data); 

NSLog(@"data:%08x", intData); // data:28450200 

Répondre

15

Cocoa (ou pour être exact le cadre Foundation) a des fonctions pour échanger le boutisme d'octets: NSSwapInt, NSSwapShort, NSSwapLong et NSSwapLongLong. Ces swaps autour des octets quoi qu'il arrive - ils font des entiers big-endian à partir des entiers petits-boutistes et vice versa.

Si vous connaissez le format que vous avez, d'autres fonctions le remplacent par l'endianness natif: NSSwapLittleIntToHost et NSSwapBigIntToHost. Il y a aussi les fonctions inverses qui passent du format natif au format little ou big endian: NSSwapHostIntToLittle et NSSwapHostIntToBig. Ceux-ci sont également disponibles pour les autres types d'entiers et de virgules flottantes. Ce qu'ils font est qu'ils appellent les fonctions d'échange primitives sur les valeurs si nécessaire. Donc, NSSwapLittleIntToHost ne fait rien tandis que NSSwapBigIntToHost renvoie le résultat de NSSwapInt sur une petite machine d'extrémité.

Notez que ceux-ci prennent les paramètres des types entiers de compilateurs et non le type NSInteger. Donc, selon que vous générez du code 32 bits ou 64 bits, vous devez utiliser différentes fonctions si vous utilisez NSInteger.

Vous ne devez pas non plus transformer votre tableau d'octets en un pointeur entier et le déréférencer. Il vaudrait mieux assembler l'entier en utilisant des opérations de décalage de bits. Votre code ne fonctionnera que si NSInteger a une largeur de 32 bits. Si c'est 64 bits, votre numéro sera corrompu ou votre programme pourrait même tomber en panne. Mais même si vous utilisez un type entier qui est toujours de 32 bits (int32_t à partir de l'en-tête C99 <stdint.h> par exemple) cela peut ne pas fonctionner comme prévu.

+0

Merci d'avoir regardé un peu autour de moi et n'ai pas trouvé NSSwapBigIntToHost. J'ai fini par faire des manipulations de bits inférieures comme vous l'avez suggéré. Je fais une petite supposition que mon code sera 32 bits dans mon code. Ce que j'ai fini par faire était de créer un char * unsf unsigned = (unsigned char *) &temp; Je fais alors une boucle et échange les octets, puis jette le tref à un entier. Pas joli mais fonctionne aussi longtemps que je suis à 32 bits. – Scott

+0

bonne question et réponse – LolaRun