Est-il nécessaire de multiplier par sizeof (char) lors de la manipulation de la mémoire?

Lorsque vous utilisez malloc et effectuez une manipulation de mémoire similaire, puis-je compter sur sizeof (char) toujours égal à 1?

Par exemple, je dois allouer de la mémoire pour N éléments de type char . Est-il nécessaire de multiplier par sizeof( char ) :

 char* buffer = malloc( N * sizeof( char ) ); 

ou puis-je compter sur sizeof (char) toujours 1 et ignorer la multiplication

 char* buffer = malloc( N ); 

Je comprends tout à fait que sizeof soit évalué lors de la compilation et que le compilateur puisse même comstackr la multiplication. La pénalité de performance sera donc minimale et probablement nulle.

Je parle principalement de la clarté et de la portabilité du code. Cette multiplication est-elle nécessaire pour le type de caractère?

Bien que cela ne soit pas nécessaire, je considère comme une bonne pratique de laisser le paramètre sizeof (char), car cela rend le code plus lisible et évite l’utilisation d’un nombre magique. En outre, si le code doit être modifié ultérieurement de manière à ne pas remplacer un caractère par un caractère, il est plus facile de changer la taille de quelque chose dans un pointeur pour cet object, il est plus facile de modifier le code que si vous avez juste un “1”.

Par définition, sizeof (char) est toujours égal à 1. Un octet est la taille du caractère en C, quel que soit le nombre de bits dans un octet (8 sur un processeur de bureau commun).

L’exemple typique où un octet n’est pas de 8 bits est le PDP-10 et d’autres anciennes architectures de type mini-ordinateur avec des octets de 9/36 bits. Mais les octets qui ne sont pas 2 ^ N deviennent extrêmement rares, je crois

Aussi, je pense que c’est un meilleur style:

 char* buf1; double* buf2; buf1 = malloc(sizeof(*buf1) * N); buf2 = malloc(sizeof(*buf2) * N); 

car cela fonctionne quel que soit le type de pointeur.

sizeof(char) est toujours 1, peu importe le type de manipulation de la mémoire que vous faites.

Cependant, sizeof(TCHAR) peut varier en fonction des options de votre compilateur.

Je considère que c’est un peu un anti-modèle . Cela indique que le programmeur ne savait pas très bien ce qu’il faisait, ce qui jette immédiatement une lumière douteuse sur le rest du code.

Certes, ce n’est pas (citation de Wikipedia) “inefficace”, mais je le trouve “loin d’être optimal”. Cela ne coûte rien au moment de l’exécution, mais il encombre le code d’inutiles déchets inutiles, tout en signalant que quelqu’un le jugeait nécessaire.

Notez également que l’expression ne s’parsing pas comme un appel de fonction: sizeof n’est pas une fonction. Vous n’appelez pas une fonction en lui passant le symbole magique char . Vous appliquez l’opérateur de préfixe unaire intégré, sizeof à une expression, et votre expression est dans ce cas un cast sur le type char , qui en C est écrit sous la forme (char) .

Il est parfaitement possible, et fortement recommandé chaque fois que possible, d’utiliser sizeof sur d’autres expressions, cela donnera alors la taille de la valeur de l’expression:

 char a; printf("A char's size is %u\n", (unsigned int) sizeof a); 

Ceci imprimera 1 , toujours, sur toutes les implémentations C conformes.

Je suis également fortement d’accord avec David Cournapeau et je pense que répéter le nom du type dans un malloc() aussi une sorte d’anti-pattern.

Au lieu de

 char *str; str = malloc(N * sizeof (char)); 

que beaucoup écriraient pour allouer un tampon de chaîne de N-caractères-capacité, je vais avec

 char *str; str = malloc(N * sizeof *str); 

Ou (pour les chaînes uniquement) omettez la sizeof comme indiqué ci-dessus, mais elle est bien sûr plus générale et fonctionne tout aussi bien pour tout type de pointeur.

Ce n’est pas nécessaire. Voir ici (par exemple).

sizeof(char) est défini par le standard C comme étant toujours 1 (octet). Notez que, puisque sizeof renvoie un nombre d’ octets, le nombre de bits par octet n’a pas d’importance (et dans la pratique, il est de 8).

Une autre chose à garder à l’esprit est que le compilateur sait statiquement que la valeur de sizeof (char) est égal à 1 et qu’il sait également que multiplier un nombre par un 1 signifie que la multiplication n’a pas besoin d’être effectuée; le compilateur va l’optimiser. Les préoccupations de performance ne doivent pas entrer en ligne de compte pour ces motifs.

De “New C standard. Un commentaire économique et culturel”.

  1. Statistiques: 2,0% de la taille sont tirés du caractère et 1,5% – du caractère unsigned char . Page 1033 dans la version 1.2 du livre.
  2. page 1037.

Le nombre de bits dans la représentation d’un type de caractère est sans importance. Par définition, le nombre d’octets en octets est un type de caractère.

Instructions de codage Les développeurs associent parfois un octet contenant toujours huit bits. Sur les hôtes où le type de caractère est 16 bits, cela peut conduire à l’hypothèse erronée que l’application de sizeof à un type de caractère retournera la valeur 2. Ces problèmes sont discutés ailleurs.

L’utilisation de sizeof (char) rend votre code plus lisible et portable.

Sur x86, nous soaps tous qu’un personnage a 1 octet. Mais l’écrire explicitement consortingbue à clarifier vos intentions, ce qui est toujours une bonne chose.

En outre, que se passe-t-il si votre code est mis sur une autre plate-forme où un caractère n’est pas 1 octet. Et si un personnage n’avait que 4 bits?

D’accord, ce n’est pas nécessaire, mais cela ne ralentit pas votre temps d’exécution et cela vous rapportera dans les rares cas où vous aurez besoin de transférer votre code vers une architecture différente.