29

我发现在VS2013strncpy_s()下定义为

errno_t __cdecl strncpy_s
(
  _Out_writes_z_(_SizeInBytes) char * _Dst, 
  _In_ rsize_t _SizeInBytes, 
  _In_reads_or_z_(_MaxCount) const char * _Src, 
  _In_ rsize_t _MaxCount
);

rsize_t是:

typedef size_t rsize_t;

我认为这是Visual Studio完成的一个技巧。但是,我发现这个函数在这个页面上定义如下

errno_t strncpy_s
(
  char *restrict dest,
  rsize_t destsz,
  const char *restrict src, 
  rsize_t count
); 

为什么rsize_t在这里定义?

如果size_t在这里使用呢?

有什么特殊情况可以使用这个rsize_t吗?

4

2 回答 2

49

您在 Microsoft 的 C++ 标准库中遇到过它,但它实际上来自 C.C 11,准确地说,这意味着它在技术上不是 C++ 的一部分。

C 11 标准,附件 K介绍了所有_s函数和相应的 typedef,包括rsize_t. 还有一个“最大值”宏RSIZE_MAX,对于典型应用来说足够大,但小于类型的实际最大值。rsize_t当类型的值超过时,安全函数什么都不做并报告错误RSIZE_MAX

这个想法是为了避免缓冲区溢出崩溃和由无效大小引起的类似错误,通常是由于使用负的大小值造成的。在 2 的补码有符号值表示(最常见的一种)中,当被视为无符号时,负数对应于非常大的数。RSIZE_MAX应该抓住这种不正确的使用。

引用 C11 (N1570), K.3.2 的“基本原理”部分:

3 非常大的对象尺寸通常表明对象的尺寸计算不正确。例如,负数在转换为无符号类型(如size_t. 此外,某些实现不支持与 type 可以表示的最大值一样大的对象size_t

4 由于这些原因,有时限制对象大小的范围以检测编程错误是有益的。对于针对具有大地址空间的机器的实现,建议将RSIZE_MAX其定义为支持的最大对象的大小中的较小者,或者(SIZE_MAX >> 1),即使此限制小于某些合法但非常大的对象的大小。针对具有小地址空间的机器的实现可能希望定义RSIZE_MAXSIZE_MAX,这意味着没有对象大小被视为违反运行时约束。


值得注意的是,附件 K 的实现很少,并且有一个提案 ( N1967 ) 将其从标准中弃用和/或删除。

于 2015-11-09T08:21:27.153 回答
15

这些 typedef 具有语义含义。显然你可以size_t在这里使用(因为它是相同的),但rsize_t更冗长:

size_t 类型通常覆盖整个地址空间。ISO/IEC TR 24731-1-2007 引入了一种新类型 rsize_t,定义为 size_t,但明确用于保存单个对象的大小。[1]

size_t这与使用代替时的情况类似unsigned int。它基本相同,但名称不同,因此您很容易理解您正在使用的内容(size_t=“某物的大小”,这意味着一个无符号整数)。

值得注意的是(正如评论所建议的那样)rsize_t在 C 规范中定义,但在 C++ 规范中没有。

于 2015-11-09T08:15:53.347 回答