为什么定义了rsize_t?

zan*_*ngw 21 c++ size-t tr24731

我发现strncpy_s()VS2013定义

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
);
Run Code Online (Sandbox Code Playgroud)

rsize_t 是:

typedef size_t rsize_t;
Run Code Online (Sandbox Code Playgroud)

我认为这是Visual Studio的一个技巧.但是,我发现此功能在此页面上定义如下

errno_t strncpy_s
(
  char *restrict dest,
  rsize_t destsz,
  const char *restrict src, 
  rsize_t count
); 
Run Code Online (Sandbox Code Playgroud)

为什么rsize_t定义在这里?如果size_t在这里使用怎么办?有什么特殊情况可以使用rsize_t吗?

Rei*_*ica 35

您在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.此外,某些实现不支持与可由类型表示的最大值一样大的对象size_t.

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


值得注意的是,附件K的实施很少,并且有一个提议(N1967)来弃用和/或从标准中删除它.

  • @zwol:有一个要求放弃它作为一个严重缺陷甚至更糟糕的坏主意:http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1967.htm (2认同)

Sin*_*all 13

这些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++规范中没有定义.

  • 很好的答案,但引用来自哪里? (2认同)
  • @sop"限制,"我会说.C11 K.3.2/4说:"由于这些原因,限制对象大小的范围以检测编程错误有时是有益的.对于具有大地址空间的机器的实现,建议将`RSIZE_MAX`定义为...... " (2认同)