【发布时间】:2020-05-06 14:33:15
【问题描述】:
size_t 和std::size_t 在声明位置、何时使用以及任何其他区别特性方面有何区别?
【问题讨论】:
-
我很想知道 C++ 规范是否将 std::size_t 链接到 C size_t 类型。
-
查看类似问题:link
size_t 和std::size_t 在声明位置、何时使用以及任何其他区别特性方面有何区别?
【问题讨论】:
C 的 size_t 和 C++ 的 std::size_t 都是相同的。
在 C 中,它在 <stddef.h> 中定义,而在 C++ 中,它在 <cstddef> 中定义,其内容与 C 标头相同(参见下面的引用)。其定义为 sizeof 运算符的result 的无符号整数类型。
C 标准在 §17.7/2 中说,
size_t 是 sizeof 运算符的结果的无符号整数类型
C++ 标准在 §18.1/3 中说(关于 cstddef 标头),
内容与标准C库头文件相同,有如下改动。
是的,两者都是一样的; 唯一的区别是C++在std命名空间中定义了size_t。
还请注意,上面的行也说 “with the following changes” 并不是指size_t。它更确切地说是指 C++ 对语言(C 中不存在)所做的新添加(大部分),这些添加也定义在同一个标题中。
维基百科有关于 size_t 的范围和存储大小的非常好的信息:
size_t的范围和存储大小
size_t 的实际类型是 平台相关; 常见错误 是假设 size_t 与 unsigned int,这可能导致 移动时出现编程错误,[3][4] 从 32 位到 64 位架构,适用于 例子。
根据 1999 ISO C 标准 (C99),size_t 是无符号数 至少 16 位的整数类型。
其余的您可以从维基百科的this page 阅读。
【讨论】:
size_t 不带using namespace std; 或using std::size_t; 是错误的。但是,大多数编译器都允许它,标准特别允许它们允许它(§D.5/3)。
<cstddef> 可能会或可能不会声明 ::size_t,因此您不能依赖它存在或不存在,除非特别包含 <stddef.h> 或 C 库中保证声明它的另一个标头。
::size_t 存在于例如<stddef.h> 中,因此您并不总是需要使用std:: 来限定它。
来自 C++03“17.4.3.1.4 类型”:
对于标准 C 库(脚注 169)中的每个类型 T,类型 ::T 和 std::T 保留给实现,并且在定义时,::T 应与 std::T 相同。
脚注 169:
这些类型是clock_t、div_t、FILE、fpos_t、lconv、ldiv_t、mbstate_t、ptrdiff_t、sig_atomic_t、size_t、time_t、tm、va_list、wctrans_t、wctype_t和wint_t。
【讨论】:
std::T 变体吗?
#include <stddef.h> 则 std::size_t 可能可用也可能不可用。如果您 #include <cstddef> 则 std::size_t 可用,但 size_t 可能不可用。
std:: 中定义它们,并且该段落说它也可以在顶级名称空间中定义它们,如果是这样,它必须在 std:: 和顶级名称空间中相同地定义它们。大多数编译器只包含 C 头文件并将名称导入到std::,因此这些符号最终都会在两者中定义。
std:: 变体。对于标准 C 头文件,我坚持使用 <xxxxx.h> - 这从来都不是问题。所以,我会使用<stddef.h> 和size_t 并且永远不会再考虑std::size_t;事实上,我从未想过有(或可能有)std::size_t。std::size_t其实就是stddef.h的size_t。
cstddef 给出以下内容:
#include <stddef.h>
namespace std
{
using ::ptrdiff_t;
using ::size_t;
}
...有效地将先前的定义带入 std 命名空间。
【讨论】:
<cstddef> 并期望获得::size_t,但如果您包含<stddef.h>,您将获得std::size_t。
<stddef.h> 只会得到::size_t。
<cstddef>,则保证您会获得std::size_t,并且您可能还会获得::size_t(但不能保证)。如果您包含<stddef.h>,那么您肯定会获得::size_t,并且您可能还会获得std::size_t(但不能保证)。它在 C++03 中有所不同,但实际上无法实现并作为缺陷修复。