Qu'est-ce que cette fonction soi-disant fait est écrire un entier non signé 32bit à un flux de fichier dans little-endian. En réalité, au lieu de faire une petite tâche simple et de faire les choses correctement, il essaie de faire deux choses ensemble et de se tromper.
Avant d'entrer dans pourquoi cela est faux, je vais répondre rapidement à la question elle-même:
- Pourquoi
UINT32
? Je ne sais pas C'est non standard et mieux être remplacé par uint32_t
. Pourquoi le 0xff
? Utilisé comme masque pour conserver les 8 bits inférieurs dans une variable plus grande (32 bits)
- Que font 4 équipes droites ici? Les décalages sont utilisés pour amener chaque octet dans l'UINT original vers les bits les plus à droite dans l'ordre correct "little-endian".
Maintenant, avec cela de la route ...
Pourquoi est-ce mal?
Un char
est garanti être at least 8 bits wide, mais pourrait être être plus grand. Cela signifie que fputc
écrira probablement 8 bits par appel, mais il pourrait écrire plus. Ce que cela signifie est que sur une certaine architecture où un caractère est (par exemple) 16 bits, la fonction écrira 64 bits par appel et ce ne sera pas du tout little-endian. De plus, la fonction vérifie avec soin les erreurs mais n'expose pas les informations d'échec pertinentes à l'appelant (combien d'octets ont été écrits?).
Quoi de mieux?
Tout d'abord, comme toujours, faire une petite chose et le faire bien:
uint32_t toLittleEndian(uint32_t v)
{
uint32_t result = v >> 24;
result |= v << 24;
result |= (v >> 8) & 0xf0;
result |= (v << 8) & 0xf00;
return result;
}
Note: cette mise en œuvre est délibérément bavard.Il y a une possibilité d'optimisation en utilisant des opérations de rotation de bits, mais C n'a pas de support natif pour cela et nécessite un code d'assemblage
Cette fonction ne convertit un big-endian valeur 32 bits à sa représentation peu endian équivalente (en fait, il alterne entre les deux et pourrait être nommé switchEndian
).
Ensuite, nous avons besoin d'écrire la valeur dans un fichier:
int write(uint32_t v, FILE *f)
{
return fwrite(&v, sizeof(v), 1, f);
}
Cela écrire exactement 32 bits de large entier, et retourne le nombre d'octets écrit. De plus, c'est réutilisable.
Ensuite, nous pourrions créer une fonction composite pratique si l'on veut:
int writeLittleEndian(uint32_t v, FILE *f)
{
return write(toLittleEndian(v), f);
}
Cet écrit un entier non signé 32 bits dans le fichier au format petit-boutiste. –
Erreur lors de la vérification d'une fonction qui écrit dans un fichier. Une découverte rare dans un monde où la vérification d'erreurs, même utile, est rarement vue. – user3386109
Question de suivi (pour tout le monde): Pouvez-vous écrire un texte lisible * sans * en utilisant des commentaires? – TobiMcNamobi