“sizeof”*真的*评估为“std: size_t”吗?可以吗?

时间:2022-04-25 17:06:41

Take the following standard passage:

以下列标准段落为例:

[C++11: 5.3.3/6]: The result of sizeof and sizeof... is a constant of type std::size_t. [ Note: std::size_t is defined in the standard header <cstddef> (18.2). —end note ]

[C+ 11: 5.3.3/6]: sizeof和sizeof…是std: size_t类型的常数。[注:std::size_t定义在标准头 (18.2)中。端注)

Now:

现在:

[C++11: 18.2/6]: The type size_t is an implementation-defined unsigned integer type that is large enough to contain the size in bytes of any object.

[c++ 11: 18.2/6]: size_t是一个实现定义的无符号整数类型,其大小足以包含任何对象的字节大小。

Granted, the passage doesn't require that size_t is a type alias defined with typedef, but since it's explicitly stated to be made available by the standard header <cstddef>, I think we can take as read that failing to include <cstddef> should remove any guarantee that size_t shall be available to a program.

当然,不需要通过size_t使用typedef定义一个类型别名,但因为它是显式声明的可用标准头< cstddef >,我认为我们可以为已读,未包括< cstddef >应该删除任何保证size_t应当提供给一个程序。

However, according to that first quote, we can regardless obtain an expression of type std::size_t.

但是,根据第一个引用,我们可以不考虑获得std::size_t类型的表达式。

We can actually demonstrate both of these facts:

我们可以证明这两个事实

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 is not visible to the program, but sizeof(0) still gives us one? Really?

size_t在程序中是不可见的,但是sizeof(0)仍然给我们一个?真的吗?

Is it therefore not correct to say that 5.3.3/6 is flawed, and that it actually has "the same type as whatever std::size_t resolves to", but not std::size_t itself?

因此,如果说5.3.3/6是有缺陷的,并且它实际上有“与std相同的类型:size_t解析为”,而不是std::size_t本身,这是不正确的吗?

Sure, the two are one and the same if std::size_t is a type alias but, again, nowhere is this actually required.

当然,如果std::size_t是一个类型别名,这两者是一个,也是一样的,但是,同样地,没有任何地方需要它。

5 个解决方案

#1


45  

Do not confuse the map for the territory.

不要把地图与领土混淆。

Types can be named by typenames. These typenames can be built-in, they can be user-defined types, or they could even be template parameters and refer to multiple different types depending on the instantiation.

类型可以由typenames命名。这些typenames可以是内置的,也可以是用户定义的类型,或者甚至可以是模板参数,根据实例化引用多个不同的类型。

But the names are not the types. Clearly standard does not mandate that all types have names -- the classic struct {} is a type without a name.

但是名字不是类型。显然,标准并不要求所有类型都有名称——典型的struct{}是没有名称的类型。

std::size_t is a typename. It names the type that sizeof(expression) returns.

std::size_t typename。它为sizeof(表达式)返回的类型命名。

The compiler could have a canonical name for the type -- __size_t would be one way for it to have a unique built-in canonical typename.

编译器可以有一个类型的规范名称——__size_t是它具有唯一的内置规范typename的一种方式。

The standard guarantees in that clause that whatever the type of sizeof(expression) is, once you #include <cstddef>, the name std::size_t now refers to that type.

该子句中的标准保证,无论sizeof(表达式)的类型是什么,一旦您#包含 ,那么std::size_t现在就引用了该类型。

In the standard, they refer to types by names. They do not say "the type that this typename refers to", but simply say "the type $NAME$". The compiler could decide that int is another name for __int_32_fast if it wanted to, and the standard would have no objection either.

在标准中,它们通过名称引用类型。他们不会说“这个typename所指的类型”,而是简单地说“类型$NAME$”。如果需要,编译器可以决定int是__int_32_fast的另一个名称,并且标准也不会反对。

This same thing happens with std::nullptr_t and std::initializer_list<Ts> and std::type_info: use of variables of those types does not always require that the header that provides you with a name for those types be included in your program.

std::nullptr_t和std::initializer_list 和std:::type_info:使用这些类型的变量并不总是要求为这些类型提供名称的头包含在程序中。

The traditional C/C++ built-in types all had canonical names that did not require a header. The downside is that this breaks existing code, as new typenames in the global scope collide with other identifiers.

传统的C/ c++内置类型都有不需要标头的规范名称。缺点是这会破坏现有的代码,因为全局范围中的新typenames会与其他标识符发生冲突。

By having "nameless types", where you can get a name for them via including a header file, we avoid that problem.

通过拥有“无名类型”,您可以通过包含头文件获得它们的名称,我们避免了这个问题。

#2


51  

The standard just mandates that the type of sizeof(expr) is the same type as std::size_t. There is no mandate that using sizeof(expr) makes the name std::size_t available and since std::size_t just names one of the the built-in integral types there isn't really a problem.

该标准只要求sizeof(expr)的类型与std::size_t的类型相同。使用sizeof(expr)并没有强制要求std: size_t这个名字是可用的,而且因为std::size_t只命名了一个内置的整型类型,所以没有问题。

#3


5  

As I understand it, this standard passage requires the following expression:

根据我的理解,这一标准段落需要以下表达:

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

will always yield true. If you use the actual identifier std::size_t, ::size_t or any other alias/typedef will be irrelevant as long as the identity of the type, as per std::typeinfo::operator==(), is preserved.

总是会产生真实的。如果您使用实际的标识符std::size_t,::size_t或任何其他别名/typedef将与类型的标识无关,就像std::typeinfo::operator==(),保存。

The same type identity issue appears in other places of the language. For example, in my 64-bit machine the following code fails to compile because of function redefinition:

相同的类型标识问题出现在语言的其他地方。例如,在我的64位机中,由于重新定义函数,以下代码无法编译:

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

void foo(unsigned long x)
{}

#4


5  

Yes.

是的。

The type yielded by sizeof is some unsigned integer type; the implementation defines which one it is.

sizeof得到的类型是某个无符号整数类型;实现定义了它是哪个。

For example, on some particular implementation, the type of a sizeof expression might be unsigned long.

例如,在某些特定的实现中,sizeof表达式的类型可能是无符号长。

std::size_t, if it's a typedef, is nothing more than an alternative name for unsigned long. So these two statements:

如果是typedef,那么size_t只不过是unsigned long的替代名称。这两个语句:

The type of sizeof ... is a constant of type unsigned long

尺寸的类型…一个常量类型是unsigned long吗?

and

The type of sizeof ... is a constant of type std::size_t

尺寸的类型…是std类型的常量::size_t ?

are saying exactly the same thing for that implementation. The type unsigned long and the type std::size_t are the same type. The difference is that the latter is accurate for all (conforming) implementations, where std::size_t might be an alias for, say, unsigned int or some other unsigned type.

对实现来说是完全一样的。类型unsigned long和类型std::size_t是相同的类型。不同的是,后者对于所有(符合要求的)实现都是准确的,其中std::size_t可能是无符号int或其他无符号类型的别名。

As far as the compiler is concerned, sizeof yields a result of type unsigned long; the compiler (as opposed to the runtime library) needn't have any knowledge of the name size_t.

就编译器而言,sizeof产生的结果是无符号长类型;编译器(与运行时库相反)不需要知道size_t这个名称。

This all assumes that std::size_t (or just size_t if you're talking about C) is a typedef. That's not spelled out in either the C or the C++ standard. Nevertheless, an implementation can straightforwardly conform to the requirements of the standard by making size_t a typedef. I don't believe there's any other portable way to satisfy those requirements. (It can't be a macro or an implementation-defined keyword because that would infringe on the user's name space, and a macro wouldn't be scoped within the std namespace.) A compiler could make size_t some implementation-specific construct other than a typedef, but since a typedef works perfectly well, there's no point in doing so. It would be nice, IMHO, if the standard stated that size_t is a typedef.

所有这些都假设std::size_t(或者只是size_t,如果你说的是C)是一个typedef。这在C和c++标准中都没有说明。然而,通过将size_t设置为typedef,实现可以直接符合标准的要求。我不相信还有其他的便携式方法可以满足这些要求。(它不能是一个宏或一个实现定义的关键字,因为这会侵犯用户的名称空间,而且一个宏不会在std名称空间中限定范围。)编译器可以使size_t某些特定于实现的构造,而不是typedef,但是由于typedef的工作非常好,所以没有必要这样做。如果标准声明size_t是一个typedef,那就太好了。

(An irrelevant aside: The real problem is that the standard refers to the result as a "constant". In ISO C, a "constant" is a token, such as an integer literal. C++, as far as I know, doesn't define the noun "constant", but it does refer to the ISO C definition of the term. sizeof ... is a constant expression; it's not a constant. Calling the result a "constant value" would have been reasonable.)

(顺便说一句:真正的问题是,标准将结果作为“常数”。在ISO C中,“常量”是一个标记,如整数文字。就我所知,c++并没有定义名词“常数”,但它确实是指这个词的ISO C定义。sizeof……是一个常量表达式;这不是一个常数。将结果称为“常量值”是合理的。

#5


2  

It is the same type but you have to include that header to use it.

它是相同的类型,但是您必须包含该头才能使用它。

#1


45  

Do not confuse the map for the territory.

不要把地图与领土混淆。

Types can be named by typenames. These typenames can be built-in, they can be user-defined types, or they could even be template parameters and refer to multiple different types depending on the instantiation.

类型可以由typenames命名。这些typenames可以是内置的,也可以是用户定义的类型,或者甚至可以是模板参数,根据实例化引用多个不同的类型。

But the names are not the types. Clearly standard does not mandate that all types have names -- the classic struct {} is a type without a name.

但是名字不是类型。显然,标准并不要求所有类型都有名称——典型的struct{}是没有名称的类型。

std::size_t is a typename. It names the type that sizeof(expression) returns.

std::size_t typename。它为sizeof(表达式)返回的类型命名。

The compiler could have a canonical name for the type -- __size_t would be one way for it to have a unique built-in canonical typename.

编译器可以有一个类型的规范名称——__size_t是它具有唯一的内置规范typename的一种方式。

The standard guarantees in that clause that whatever the type of sizeof(expression) is, once you #include <cstddef>, the name std::size_t now refers to that type.

该子句中的标准保证,无论sizeof(表达式)的类型是什么,一旦您#包含 ,那么std::size_t现在就引用了该类型。

In the standard, they refer to types by names. They do not say "the type that this typename refers to", but simply say "the type $NAME$". The compiler could decide that int is another name for __int_32_fast if it wanted to, and the standard would have no objection either.

在标准中,它们通过名称引用类型。他们不会说“这个typename所指的类型”,而是简单地说“类型$NAME$”。如果需要,编译器可以决定int是__int_32_fast的另一个名称,并且标准也不会反对。

This same thing happens with std::nullptr_t and std::initializer_list<Ts> and std::type_info: use of variables of those types does not always require that the header that provides you with a name for those types be included in your program.

std::nullptr_t和std::initializer_list 和std:::type_info:使用这些类型的变量并不总是要求为这些类型提供名称的头包含在程序中。

The traditional C/C++ built-in types all had canonical names that did not require a header. The downside is that this breaks existing code, as new typenames in the global scope collide with other identifiers.

传统的C/ c++内置类型都有不需要标头的规范名称。缺点是这会破坏现有的代码,因为全局范围中的新typenames会与其他标识符发生冲突。

By having "nameless types", where you can get a name for them via including a header file, we avoid that problem.

通过拥有“无名类型”,您可以通过包含头文件获得它们的名称,我们避免了这个问题。

#2


51  

The standard just mandates that the type of sizeof(expr) is the same type as std::size_t. There is no mandate that using sizeof(expr) makes the name std::size_t available and since std::size_t just names one of the the built-in integral types there isn't really a problem.

该标准只要求sizeof(expr)的类型与std::size_t的类型相同。使用sizeof(expr)并没有强制要求std: size_t这个名字是可用的,而且因为std::size_t只命名了一个内置的整型类型,所以没有问题。

#3


5  

As I understand it, this standard passage requires the following expression:

根据我的理解,这一标准段落需要以下表达:

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

will always yield true. If you use the actual identifier std::size_t, ::size_t or any other alias/typedef will be irrelevant as long as the identity of the type, as per std::typeinfo::operator==(), is preserved.

总是会产生真实的。如果您使用实际的标识符std::size_t,::size_t或任何其他别名/typedef将与类型的标识无关,就像std::typeinfo::operator==(),保存。

The same type identity issue appears in other places of the language. For example, in my 64-bit machine the following code fails to compile because of function redefinition:

相同的类型标识问题出现在语言的其他地方。例如,在我的64位机中,由于重新定义函数,以下代码无法编译:

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

void foo(unsigned long x)
{}

#4


5  

Yes.

是的。

The type yielded by sizeof is some unsigned integer type; the implementation defines which one it is.

sizeof得到的类型是某个无符号整数类型;实现定义了它是哪个。

For example, on some particular implementation, the type of a sizeof expression might be unsigned long.

例如,在某些特定的实现中,sizeof表达式的类型可能是无符号长。

std::size_t, if it's a typedef, is nothing more than an alternative name for unsigned long. So these two statements:

如果是typedef,那么size_t只不过是unsigned long的替代名称。这两个语句:

The type of sizeof ... is a constant of type unsigned long

尺寸的类型…一个常量类型是unsigned long吗?

and

The type of sizeof ... is a constant of type std::size_t

尺寸的类型…是std类型的常量::size_t ?

are saying exactly the same thing for that implementation. The type unsigned long and the type std::size_t are the same type. The difference is that the latter is accurate for all (conforming) implementations, where std::size_t might be an alias for, say, unsigned int or some other unsigned type.

对实现来说是完全一样的。类型unsigned long和类型std::size_t是相同的类型。不同的是,后者对于所有(符合要求的)实现都是准确的,其中std::size_t可能是无符号int或其他无符号类型的别名。

As far as the compiler is concerned, sizeof yields a result of type unsigned long; the compiler (as opposed to the runtime library) needn't have any knowledge of the name size_t.

就编译器而言,sizeof产生的结果是无符号长类型;编译器(与运行时库相反)不需要知道size_t这个名称。

This all assumes that std::size_t (or just size_t if you're talking about C) is a typedef. That's not spelled out in either the C or the C++ standard. Nevertheless, an implementation can straightforwardly conform to the requirements of the standard by making size_t a typedef. I don't believe there's any other portable way to satisfy those requirements. (It can't be a macro or an implementation-defined keyword because that would infringe on the user's name space, and a macro wouldn't be scoped within the std namespace.) A compiler could make size_t some implementation-specific construct other than a typedef, but since a typedef works perfectly well, there's no point in doing so. It would be nice, IMHO, if the standard stated that size_t is a typedef.

所有这些都假设std::size_t(或者只是size_t,如果你说的是C)是一个typedef。这在C和c++标准中都没有说明。然而,通过将size_t设置为typedef,实现可以直接符合标准的要求。我不相信还有其他的便携式方法可以满足这些要求。(它不能是一个宏或一个实现定义的关键字,因为这会侵犯用户的名称空间,而且一个宏不会在std名称空间中限定范围。)编译器可以使size_t某些特定于实现的构造,而不是typedef,但是由于typedef的工作非常好,所以没有必要这样做。如果标准声明size_t是一个typedef,那就太好了。

(An irrelevant aside: The real problem is that the standard refers to the result as a "constant". In ISO C, a "constant" is a token, such as an integer literal. C++, as far as I know, doesn't define the noun "constant", but it does refer to the ISO C definition of the term. sizeof ... is a constant expression; it's not a constant. Calling the result a "constant value" would have been reasonable.)

(顺便说一句:真正的问题是,标准将结果作为“常数”。在ISO C中,“常量”是一个标记,如整数文字。就我所知,c++并没有定义名词“常数”,但它确实是指这个词的ISO C定义。sizeof……是一个常量表达式;这不是一个常数。将结果称为“常量值”是合理的。

#5


2  

It is the same type but you have to include that header to use it.

它是相同的类型,但是您必须包含该头才能使用它。