size_t的正确定义是什么?

时间:2015-08-29 13:23:48

标签: c c99 c11 size-t

首先,我的意思是'正确定义'?

例如,“C编程语言”第2版中的K& R,在 2.2数据类型和大小部分中,对整数做出非常明确的陈述:

  
      
  • 整数类型有shortintlong。他们需要重复不同边界的价值观。
  •   
  • int是特定硬件的“自然”大小的数字,因此也可能是最快的。
  •   
  • 整数类型shortintlong的大小完全取决于实现。
  •   
  • 但他们有限制。
  •   
  • shortint至少应保留16位。
  •   
  • long至少应保留32位。
  •   
  • short> = int> = long
  •   

这非常明确且毫不含糊。 size_t类型不是这种情况。在K& R 5.4地址算术中,他们说:

  
      
  • ... size_tsizeof运算符返回的无符号整数类型。
  •   
  • sizeof运算符产生存储其操作数类型对象所需的字节数。
  •   

C99 standard draft 6.5.3.4 sizeof运算符中,他们说:

  
      
  • 结果的值是实现定义的,其类型(无符号整数类型)是size_t,在<stddef.h>中定义(和其他   头)。
  •   

7.17通用定义

  
      
  • size_t,这是sizeof运算符的结果的无符号整数类型;
  •   

7.18.3其他整数类型的限制

  
      
  • size_t SIZE_MAX 65535
  • 的限制   

还有一篇有用的文章 - Why size_t matters。它说:

  
      
  • 好的,让我们试着想象一下,如果没有size_t会是什么。
  •   
  • 例如,我们从void *memcpy(void *s1, void const *s2, size_t n);
  • 获取<string.h>标准函数   
  • 我们使用int代替size_t n参数。
  •   
  • 但是记忆的大小不能是负数,所以最好采取unsigned int
  •   
  • 很好,好像我们现在很开心,没有size_t
  •   
  • 但是unsigned int的大小有限 - 如果有一台机器可以复制大于unsigned int的内存块呢?
  •   
  • 好的,我们现在使用unsigned long,现在我们很开心吗?
  •   
  • 但对于那些使用较小内存块运行的计算机,unsigned long效率低下,因为long不是“自然”   对于他们来说,他们必须执行额外的操作才能使用   long秒。
  •   
  • 因此,我们需要size_t - 来表示内存大小,特定硬件可以同时运行。在某些机器上它会   等于int,在其他人 - 等于long,具体取决于哪种类型   他们最有效率。
  •   

我从中理解的是size_tsizeof运算符严格限制。因此size_t表示对象的最大大小(以字节为单位)。它也可能表示特定CPU模型可以同时移动的字节数。

但这里仍有许多神秘之处:

  • 就C而言,“对象”是什么?
  • 为什么它被限制为65535,这是最大数字,可以用16位表示? embedded.com 上的文章说,size_t也可能是32位。
  • K&amp; R说,int平台具有“自然”大小,可以等于intlong。那么,如果它是“自然的”,为什么不使用它代替size_t

更新

有类似的问题:

What is size_t in C?

但是它的答案并未提供明确的定义或与权威来源的链接(如果不算维基百科那样)。

我想知道何时使用size_t,什么时候不使用size_t,为何引入它,以及它真正代表什么。

4 个答案:

答案 0 :(得分:3)

  

就C而言,“对象”是什么?

“对象”是一个定义的术语。 C99标准将其定义为:“执行环境中的数据存储区域,其内容可以表示值”(第3.14节)。一个更通俗的定义可能是“存储在内存中的价值”。对象具有不同的大小,具体取决于存储的值的类型。该类型不仅包括charint等简单类型,还包括结构和数组等复杂类型。例如,数组的存储是对象,其中每个元素都是对象

  

为什么它被限制为65535,这是最大数字,可以用16位表示? embedded.com上的文章说,size_t也可能是32位。

你误解了。重新阅读第7.18.3节的前两段。 SIZE_MAX表示类型size_t的最大值,但其实际值取决于实现。标准中给出的值是 minimum 值。在大多数实现中,它更大。

  

K&amp; R说,int具有平台的“自然”大小,并且它可以等于int或long。那么,如果它是“自然的”,为什么不使用它而不是size_t?

因为没有特别的原因,对象的最大大小应限制在单个机器字中可表达的字节数(这几乎与“自然大小”的含义相同)。在intlong大小不同的情况下,也不清楚哪一个应与size_t对应,如果有的话。使用size_t而不是其中一个摘要远离计算机详细信息并使您的代码更具可移植性。

响应更新:

  

我想知道,何时使用size_t,何时不使用size_t,为何引入它以及它实际代表什么。

size_t主要定义为sizeof的结果类型。因此,它“真正代表”的是对象的大小。

使用size_t保存表示对象大小或与对象大小相关的值。这显然是它的用途。在大多数情况下,您可以通过类型匹配来完成此操作:使用类型size_t的变量来存储声明为具有该类型的值,例如某些函数的返回值(例如strlen())和某些运营商的结果(例如sizeof)。

请勿将size_t用于表示对象大小以外的其他值或与其密切相关的值(例如对象大小的总和或正差异)。

答案 1 :(得分:2)

  

为什么它被限制为65535,这是最大数字,可以用16位表示?

至少16位。

  

根据1999 ISO C标准(C99),size_t是至少16位的无符号整数类型(参见7.17和7.18.3节)。

为什么要使用size_t

size_t是一种保证包含任何数组索引的类型。

size_t可以是任何一个(也可以是除此之外的任何其他内容)unsigned charunsigned shortunsigned intunsigned long或{{1根据实施情况而定。

要使用unsigned long longunsigned int代替unsigned long,原因类似于它们不是唯一的无符号整数类型。

其目的是减轻程序员不必担心哪些预定义类型用于表示大小。

在一个系统上,使用size_t表示大小可能是有意义的;另一方面,使用unsigned intunsigned long可能更有意义。

因此,使用unsigned long long增加了代码可能更具可移植性的优势。

答案 2 :(得分:2)

  

何时使用size_t

使用size_t表示非负索引,并使用可追溯到sizeof表达式的值。

  

何时不使用size_t

每当某个值可能为负时,例如当你减去指针时。这允许指针指向同一个数组,但它可能会产生一个负数,具体取决于指针的相对位置。为此情况定义了另一种类型ptrdiff_t

  

为什么要介绍

标准的设计者可以选择引入单独的类型,或者要求现有类型能够容纳尺寸。第一种选择为编译器编写者提供了更大的灵活性,因此设计人员采用了单独的类型。

  

它真正代表什么

它能够表示内存中对象的大小,可以是数组,structstruct数组,struct s数组,或其他任何东西。大小以字节表示。

该类型也非常方便用于非负索引,因为它可以表示最大粒度的任何大小的结构的索引(即,char的最大可能数组的索引,因为该标准要求char具有尽可能小的1}。

答案 3 :(得分:1)

没有(单一)“正确的定义”。如上所述,它的实现已定义。

  

我想知道,何时使用size_t,

size_tsizeof()相关的所有内容。也就是说,对象的技术规模。

  

何时不使用size_t,

用于正常(面向域)计数和数字。

  

为什么它被引入以及它真正代表什么。

它提供了一种独立于实现的方式来处理大小和分配,即它允许您编写可移植代码。