web-dev-qa-db-fra.com

Serait-ce le cas que sizeof (T *)! = Sizeof (const T *)?

Je discute avec mon patron à ce sujet. Ils disent "oui, ils peuvent être différents".

Est-il possible que sizeof(T*) != sizeof(const T*) pour un type T?

67
P45 Imminent

Non, ils ne peuvent pas être différents. Pour T1 Et T2 Suffisamment différents, sizeof(T1 *) peut être différent de sizeof(T2 *), mais si T2 Est juste const T1, puis:

.9.2 Types composés [basic.compound]

3 [...] Les pointeurs vers les versions (3.9.3) qualifiées cv et non cv des types compatibles avec la disposition doivent avoir les mêmes exigences de représentation et d'alignement des valeurs (3.11). [...]

Et tout type T est compatible avec lui-même:

.9 Types [basic.types]

11 Si deux types T1 Et T2 Sont du même type, alors T1 Et T2 Sont compatibles avec la disposition types. [...]


La représentation des valeurs est en relation avec la représentation des objets, vous ne pouvez pas avoir la même représentation des valeurs sans avoir également la même représentation des objets. Ce dernier signifie que le même nombre de bits est requis.

.9 Types [basic.types]

4 La représentation d'objet d'un objet de type T est la séquence de [~ # ~ ] n [~ # ~] unsigned char objets repris par l'objet de type T, où [~ # ~] n [~ # ~] est égal à sizeof(T). La représentation de valeur d'un objet est l'ensemble de bits contenant la valeur de type T. Pour les types trivialement copiables, la représentation de valeur est un ensemble de bits dans la représentation d'objet qui détermine une valeur , qui est un élément discret d'une définition définie par l'implémentation ensemble de valeurs.44

44) Le but est que le modèle de mémoire de C++ soit compatible avec celui du langage de programmation C. ISO/IEC 9899.

Le point de l'exigence, la raison pour laquelle il ne dit pas seulement que les deux types ont la même représentation d'objet, est que T * Et const T * Ont non seulement le même nombre de bits, mais aussi que ce sont les mêmes bits dans T * et const T * qui composent la valeur. Ceci est destiné à garantir non seulement que sizeof(T *) == sizeof(const T *), mais cela signifie même que vous pouvez utiliser memcpy pour copier une valeur de pointeur T * Vers un pointeur const T * valeur ou vice versa et obtenir un résultat significatif, exactement le même résultat que vous obtiendriez avec const_cast.

Les exigences d'alignement fournissent également des garanties supplémentaires, mais elles sont compliquées à expliquer correctement et ne sont pas directement pertinentes pour cette question, et il y a des problèmes dans la norme qui sapent certaines des garanties prévues, donc je pense qu'il vaut mieux ignorer ici.

81
user743382

Microchip a publié un tel compilateur C où la sizeof(T*) valait 2 mais sizeof(const T*) valait 3.

Le compilateur C n'était pas conforme aux normes à plusieurs égards, donc cela ne dit rien sur la validité (je soupçonne que ce n'est pas le cas et d'autres réponses sont d'accord).

8
Joshua

Hmm, c'est très ésotérique, mais je pense qu'en théorie il y a pourrait une architecture qui a, disons, 256 octets de RAM à l'adresse 0 et, disons, quelques kilo-octets de ROM dans les adresses supérieures. Et il y a pourrait un compilateur qui créerait un pointeur de 8 bits pour int *i Car 8 bits sont suffisants pour contenir l'adresse de n'importe quel objet dans la zone très limitée RAM et tout objet mutable est bien entendu implicitement connu dans la zone RAM. Les pointeurs de type const int *i Auraient besoin de 16 bits pour pouvoir pointer vers n'importe quel emplacement dans l'espace d'adressage. Le pointeur 8 bits int *i Peut être converti en un pointeur 16 bits const int *i (Mais pas l'inverse) afin que l'exigence de castabilité de la norme C soit satisfaite.

Mais s'il existe une telle architecture dans existense, j'aimerais bien la voir (mais pas écrire du code pour ça) :)

5
PkP

En ce qui concerne le C++ standard, ils ne peuvent pas différer. C et C++ sont similaires sur ce point.

Mais il existe de nombreuses architectures avec des compilateurs écrits pour eux qui ne suivent pas cette règle. En effet, nous ne parlons pas vraiment de C++ standard, et certains diront alors que le langage n'est pas C++, mais ma lecture de votre question (avant l'ajout de la balise juriste du langage) concerne davantage la possibilité.

Dans ce cas, c'est possible. Vous pouvez très bien constater qu'un pointeur vers ROM (donc const) est d'une taille différente d'un pointeur vers RAM (const ou non const.)

Si vous savez avec certitude que votre code ne se terminera que sur un compilateur de plaintes standard, votre hypothèse est correcte. Sinon, je réfléchirais attentivement à ce que leurs tailles soient les mêmes.

2
Bathsheba