2010-12-07 33 views
3

EDIT: Le mauvais type de num2 a été corrigé.Coulée d'un tableau de caractères dans un entier

Bonjour,

J'ai quelques tableaux de caractères de taille connue qui contient des données entières brutes lues à partir d'un fichier binaire.

La taille de tous ces tableaux a la taille d'un nombre entier.

Je voudrais demander si l'opération suivante est sûre et précise dans TOUTES les situations normales, en supposant que l'endianness des données brutes et l'ordinateur qui exécute ce code est d'accord.

char arr1[4] = { ... }; 
char arr2[2] = { ... }; 

uint32_t num1 = *static_cast<uint32_t*>(arr1); /* OR num1 = *(uint32_t*)arr1 in C */ 
uint16_t num2 = *static_cast<uint16_t*>(arr2); /* OR num2 = *(uint32_t*)arr2 in C */ 

Merci!

+3

Puisqu'il s'agit d'un fichier binaire, vous feriez mieux de lire les entiers bruts dans un tableau d'entiers. – chrisaycock

+1

Ne déclarez jamais plus d'une variable à la fois. Cela peut conduire à des bugs subtils. https://www.securecoding.cert.org/confluence/display/seccode/DCL04-C.+Do+not+declare+more+than+one+variable+per+declaration –

+0

La conversion directe de la mémoire de caractères en entier ne fonctionne que sur les processeurs avec alignement des octets, pas d'alignement des mots. Si vous utilisez uniquement/toujours un Intel x86, ce ne sera pas un problème. –

Répondre

3

Il est techniquement sûr, mais il y a quelques choses que je considérerais:

  • Ajouter à la compilation pour vérifier les affirme tailles. Êtes-vous sûr que votre tableau char est égal à sizeof (your_int_type)? Votre num2 est un bon exemple de l'importance de ce problème - votre faute de frappe entraînerait un comportement indéfini.
  • Considérons l'alignement. Êtes-vous sûr que votre tableau char est sur une limite de 4 octets (en supposant que votre int est de 4 octets)? Par exemple, PowerPC se bloque si vous essayez de lire un int à partir d'un pointeur non aligné.
+0

Le type de l'entier correspondant est déterminé dans mon programme avec du code de métaprogrammation de gabarit, donc le type correct est garanti. –

+1

Existe-t-il un moyen de vérifier que la matrice char est vraiment dans une limite de 4 octets? –

+0

+1. Je ne savais pas cela à propos de l'alignement ... – Cameron

1

Cela devrait être en sécurité:

char arr1[4] = { ... }; 

uint32_t num1; 

memcpy(&num1, arr1, sizeof num1); 

Mais pourquoi est-arr2 seulement 2 octets grand? Est-ce une faute de frappe?

+1

Vous ne savez pas combien de bits sont dans un octet. –

+0

@Dibling: Tant que vous contrôlez l'emplacement du code, vous le faites. –

0

Une approche plus sûre consisterait à utiliser une macro (par exemple MAKEDWORD) pour placer les octets dans leur ordre approprié.

0

Si vous êtes sûr que les réseaux sont correctement alignés, il ne devrait pas y avoir de problème (compte tenu de l'endianness).

Dans le code, cependant, je ne sais pas ce que vous faites avec arr2, car il s'agit de 16 bits, et vous en lisez une quantité de 32 bits.

0

Oui, cela devrait fonctionner correctement (sous votre hypothèse d'endianness), puisque la représentation de ces octets en mémoire est la même, qu'elle soit interprétée comme un tableau d'octets ou un entier.

Vraiment tout ce que vous faites est de changer le type, pas les données.

5

Vous devez utiliser une union.

union charint32 { 
    char arr1[4]; 
    uint32_t num; 
}; 

Cela simplifiera le stockage et la diffusion pour vous.

+1

Tant que l'ordre des octets est le même, cela fonctionnera et n'aura pas de problèmes d'alignement des types de données. –

+0

+1. Cela fonctionnera. Ce n'est pas conforme à la norme C++, mais là encore, c'est probablement l'une des règles les plus violées. – EboMike