Conclusion finale: l'arithmétique sur a void*
est illégale en C et C ++.
GCC l'autorise comme extension, voir Arithmétique sur void
- et pointeurs de fonction (notez que cette section fait partie du chapitre "Extensions C" du manuel). Clang et ICC autorisent probablement l' void*
arithmétique à des fins de compatibilité avec GCC. D'autres compilateurs (comme MSVC) interdisent l'arithmétique sur void*
, et GCC l'interdit si l' -pedantic-errors
indicateur est spécifié, ou si l' -Werror-pointer-arith
indicateur est spécifié (cet indicateur est utile si votre base de code doit également compiler avec MSVC).
La norme C parle
Les citations sont tirées du projet n1256.
La description standard de l'opération d'ajout indique:
6.5.6-2: Pour l'addition, soit les deux opérandes doivent être de type arithmétique, soit un opérande doit être un pointeur vers un type d'objet et l'autre doit être de type entier.
Donc, la question ici est de savoir si void*
est un pointeur vers un "type d'objet", ou de manière équivalente, s'il void
s'agit d'un "type d'objet". La définition du "type d'objet" est:
6.2.5.1: Les types sont divisés en types d'objets (types qui décrivent complètement les objets), types de fonction (types qui décrivent des fonctions) et types incomplets (types qui décrivent des objets mais manquent des informations nécessaires pour déterminer leurs tailles).
Et la norme définit void
comme:
6.2.5-19: le void
type comprend un ensemble vide de valeurs; c'est un type incomplet qui ne peut pas être complété.
Puisqu'il void
s'agit d'un type incomplet, ce n'est pas un type d'objet. Ce n'est donc pas un opérande valide pour une opération d'addition.
Par conséquent, vous ne pouvez pas effectuer d'arithmétique de pointeur sur un void
pointeur.
Remarques
À l'origine, on pensait que l' void*
arithmétique était autorisée, en raison de ces sections de la norme C:
6.2.5-27: Un pointeur vers void doit avoir les mêmes
exigences de représentation et d'alignement qu'un pointeur vers un type de caractère.
cependant,
Les mêmes représentation et alignement des
exigences sont censées impliquer interchangeabilité comme arguments à des fonctions, des valeurs de retour des fonctions et des membres des syndicats.
Cela signifie donc que cela printf("%s", x)
a la même signification, qu'il x
soit de type char*
ou void*
, mais cela ne signifie pas que vous pouvez faire de l'arithmétique sur un void*
.
Note de l'éditeur: Cette réponse a été modifiée pour refléter la conclusion finale.