60 votes

Est-ce que "sizeof` *vraiment* évaluer à un" std::size_t`? Peut-il?

Prendre la suite de la norme passage:

[C++11: 5.3.3/6]: Le résultat d' sizeof et sizeof... est une constante de type std::size_t. [ Note: std::size_t est défini dans la norme en-tête <cstddef> (18.2). -la note de fin ]

Maintenant:

[C++11: 18.2/6]: Type size_t est une mise en œuvre définies par type entier non signé qui est assez grand pour contenir la taille en octets d'un objet quelconque.

Accordé, le passage n'exige pas l' size_t est un alias de type défini avec typedef, mais puisqu'il est explicitement indiqué par la norme en-tête <cstddef>, je pense que nous pouvons prendre comme lu que de ne pas inclure <cstddef> devrait supprimer toute garantie que l' size_t doit être disponible pour un programme.

Toutefois, selon cette première citation, nous pouvons indépendamment obtenir une expression de type std::size_t.

On peut en fait démontrer ces deux faits:

int main()
{
    typedef decltype(sizeof(0)) my_size_t;

    my_size_t x   = 0;  // OK
    std::size_t y = 1;  // error: 'size_t' is not a member of 'std'
}

std::size_t n'est pas visible pour le programme, mais sizeof(0) nous donne encore un? Vraiment?

Est-il donc pas correct de dire qu' 5.3.3/6 est imparfait, et qu'il a effectivement "du même type que ce que std::size_t décide de", mais pas std::size_t lui-même?

Bien sûr, les deux sont une seule et même si std::size_t est un alias de type, mais, encore une fois, cela est réellement nécessaire.

52voto

Dietmar Kühl Points 70604

Le standard exige que le type d' sizeof(expr) est du même type que std::size_t. Il n'y a pas de mandat que l'utilisation d' sizeof(expr) a fait le nom de std::size_t disponible et depuis std::size_t seulement des noms de la la construit-dans les types intégraux il n'est pas vraiment un problème.

47voto

Yakk Points 31636

Ne pas confondre la carte pour le territoire.

Les Types peuvent être nommés par typenames. Ces typenames peut être intégré dans le programme, ils peuvent être des types définis par l'utilisateur, ou ils pourraient même être template paramètres et reportez-vous à plusieurs types différents en fonction de l'instanciation.

Mais les noms ne sont pas les types. Clairement la norme n'impose pas que tous les types ont des noms -- la classique struct {} est un type sans nom.

std::size_t est un typename. Il nomme le type d' sizeof(expression) de rendement.

Le compilateur pourrait avoir un nom canonique du type -- __size_t serait une façon pour elle d'avoir un unique intégré canonique typename.

La norme garantit dans cette clause que, quel que soit le type d' sizeof(expression) est, une fois que vous #include <cstddef>, le nom de l' std::size_t fait maintenant référence à ce type.

Dans la norme, ils se réfèrent à des types de noms. Ils ne disent pas "le type que ce nom fait référence à", mais simplement dire "le type du NOM de$$". Le compilateur pourrait décider qu' int est un autre nom pour __int_32_fast s'il le voulait, et le standard n'ont pas d'objection non plus.

Cette même chose qui se passe avec std::nullptr_t et std::initializer_list<Ts> et std::type_info: l'utilisation de variables de ces types n'est pas toujours besoin que l'en-tête qui vous fournit un nom pour ces types de être inclus dans votre programme.

La traditionnelle C/C++ intégré dans tous les types avaient des noms canoniques qui n'a pas besoin d'un en-tête. L'inconvénient est que cela rompt avec le code existant, en tant que nouveau typenames dans la portée globale entrer en collision avec d'autres identifiants.

"Nameless types", où vous pouvez obtenir un nom pour eux par l'intermédiaire notamment d'un fichier d'en-tête, nous éviter ce problème.

5voto

rodrigo Points 34500

Si je comprends bien, cette norme passage nécessite l'expression suivante:

typeid(sizeof(0)) == typeid(std::size_t)

sera toujours céder true. Si vous utilisez l'identifiant std::size_t, ::size_t ou de toute autre alias/typedef sera pas pertinent, pour autant que l'identité du type, comme par std::typeinfo::operator==(), est conservé.

Le même type d'identité en question apparaît dans d'autres endroits de la langue. Par exemple, dans ma machine 64 bits, le code suivant ne compile en raison de la redéfinition de la fonction:

#include <cstddef>
void foo(std::size_t x)
{}

void foo(unsigned long x)
{}

5voto

Keith Thompson Points 85120

Oui.

Le type donné par sizeof est un certain type entier non signé; la mise en œuvre définit de laquelle il s'agit.

Par exemple, sur certains de la mise en œuvre, le type d'un sizeof expression pourrait être unsigned long.

std::size_t, si c'est un typedef, n'est rien de plus qu'un autre nom pour l' unsigned long. Donc, ces deux énoncés:

Le type d' sizeof ... est une constante de type unsigned long

et

Le type d' sizeof ... est une constante de type std::size_t

disons exactement la même chose pour que la mise en œuvre. Le type unsigned long et le type std::size_t sont du même type. La différence est que ce dernier est exacte pour tous (conforme) implémentations, où std::size_t pourrait être un alias pour, disons, unsigned int ou quelque autre type non signé.

Aussi loin que le compilateur est concerné, sizeof donne un résultat de type unsigned long; le compilateur (par opposition à la bibliothèque d'exécution) n'ont pas connaissance du nom size_t.

Tout cela suppose que std::size_t (ou juste size_t si vous parlez C) est une définition de type. Ce n'est pas énoncée dans le C ou le C++ standard. Néanmoins, une mise en œuvre peut carrément être conformes aux exigences de la norme en rendant size_t un typedef. Je ne crois pas qu'il y a d'autres portables de façon à satisfaire à ces exigences. (Il ne peut pas être une macro ou une mise en œuvre définies par mot-clé parce que ce serait empiéter sur le nom de l'utilisateur de l'espace, et une macro ne serait pas étendue à l'intérieur de l' std espace de noms). Un compilateur pourrait faire size_t certains de la mise en œuvre spécifique de la construction d'autre qu'une définition de type, mais depuis un typedef fonctionne parfaitement bien, il n'y a aucun point à le faire. Il serait bon, à mon humble avis, si la norme a déclaré qu' size_t est un typedef.

(Inutiles de côté: Le vrai problème, c'est que la norme renvoie le résultat sous forme d'une "constante". En ISO C, une "constante" est un jeton, comme un littéral entier. C++, autant que je sache, ne définit pas le mot "constante", mais il fait référence à la norme ISO C définition du terme. sizeof ... est une constante de l'expression; ce n'est pas une constante. Appelant le résultat d'une "valeur constante" aurait été raisonnable.)

2voto

user2030677 Points 970

C'est le même type, mais vous devez inclure cet en-tête pour l'utiliser.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X