代码之家  ›  专栏  ›  技术社区  ›  Rob

无符号整数与大小

  •  455
  • Rob  · 技术社区  · 16 年前

    我注意到现代C和C++代码似乎都在使用。 size_t 而不是 int / unsigned int 几乎所有地方——从C字符串函数的参数到STL。我很好奇这样做的原因及其带来的好处。

    8 回复  |  直到 6 年前
        1
  •  360
  •   Craig M. Brandenburg Martin    9 年前

    这个 size_t 类型是无符号整数类型,它是 sizeof 操作员(和 offsetof operator),因此它保证足够大,可以容纳系统可以处理的最大对象的大小(例如,8GB的静态数组)。

    这个 西泽特 类型可以大于、等于或小于 unsigned int ,您的编译器可能会对其进行假设以进行优化。

    您可以在C99标准第7.17节中找到更精确的信息,该标准草案可在以下网址上获得: pdf 格式,或在C11标准第7.19节中,也可用作 pdf draft .

        2
  •  92
  •   StaceyGirl    6 年前

    经典的C语言(Brian Kernighan和Dennis Ritchie在C编程语言中描述的C语言的早期方言,Prentice Hall,1978)没有提供 size_t . C标准委员会介绍 西泽特 消除可移植性问题

    Explained in detail at embedded.com (with a very good example)

        3
  •  65
  •   StaceyGirl    6 年前

    简而言之, size_t 从不为负,它最大化了性能,因为typedef是一个无符号整数类型,它足够大(但不太大),以表示目标平台上最大可能对象的大小。

    尺寸不应该是负数,事实上 西泽特 是无符号类型。此外,因为 西泽特 是无符号的,您可以存储大约是相应有符号类型中两倍大的数字,因为我们可以使用符号位来表示大小,就像无符号整数中的所有其他位一样。当我们再获得一个位时,我们将可以表示的数字范围乘以大约2的因数。

    所以,你会问,为什么不使用 unsigned int ?它可能无法容纳足够大的数字。在一个实现中, 无符号整型 是32位,它能代表的最大数字是 4294967295 . 某些处理器(如IP16L32)可以复制大于 四十二亿九千四百九十六万七千二百九十五 字节。

    所以,你问,为什么不使用 unsigned long int ?它在某些平台上需要性能代价。标准C要求 long 至少占用32位。IP16L32平台实现每一个32位作为一对16位字。几乎所有这些平台上的32位操作符都需要两个指令,如果不是更多的话,因为它们在两个16位块中处理32位。例如,移动32位的长度通常需要两个机器指令——一个指令移动16位块。

    使用 西泽特 避免这种性能损失。根据 this fantastic article ,“Type 西泽特 是一个typedef,它是一些无符号整数类型的别名,通常 无符号整型 unsigned long ,但可能甚至 unsigned long long . 每个标准的C实现都应该选择足够大的无符号整数(但不大于需要的整数),以表示目标平台上最大可能对象的大小。”

        4
  •  48
  •   Kevin S.    16 年前

    大小类型是sizeof运算符返回的类型。它是一个无符号整数,能够以字节表示主机上支持的任何内存范围的大小。它(通常)与ptrdiff_t有关,因为ptrdiff_t是一个有符号整数值,这样sizeof(ptrdiff_t)和sizeof(sizeof)相等。

    编写C代码时,应该 总是 处理内存范围时,请使用大小t。

    另一方面,int类型基本上定义为主机可以用来最有效地执行整数运算的(有符号)整数值的大小。例如,在许多老式PC机上,sizeof(size_t)的值为4(字节),sizeof(int)的值为2(字节)。16位算术比32位算术快,尽管CPU可以处理高达4 GiB的(逻辑)内存空间。

    只有当您关心效率时才使用int类型,因为它的实际精度在很大程度上取决于编译器选项和机器体系结构。特别是,C标准规定了以下不变量:sizeof(char)<=sizeof(short)<=sizeof(int)<=sizeof(long),对程序员可用于这些基本类型的精度的实际表示没有其他限制。

    注意:这与Java中的不同,它实际上为每个类型的字符“字节”、“短”、“int”和“长”指定了位精度。

        5
  •  23
  •   Maciej Hehl    16 年前

    类型大小必须足够大以存储任何可能对象的大小。无符号int不必满足该条件。

    例如,在64位系统中,in t和unsigned in t的宽度可能为32位,但大小必须足够大,以存储大于4g的数字。

        6
  •  3
  •   Graeme Burke    11 年前

    本节选自glibc手册0.02,在研究该主题时也可能相关:

    在2.4版之前,gcc的大小、类型和版本存在潜在问题。ANSIC要求大小不总是无符号类型。为了与现有系统的头文件兼容,gcc在 stddef.h' to be whatever type the system's sys/types.h'将其定义为。大多数在“sys/types.h”中定义大小的UNIX系统都将其定义为带符号的类型。库中的某些代码取决于无符号类型的大小,如果有符号,则无法正常工作。

    要求大小不带符号的GNU C库代码是正确的。将大小定义为带符号类型不正确。我们计划在2.4版中,gcc总是将大小定义为无符号类型,并且 fixincludes' script will massage the system's sys/types.h'以避免与此冲突。

    同时,我们通过明确地告诉GCC在编译GNUC库时使用无符号类型来解决这个问题。` configure'将自动检测gcc使用什么类型的大小来覆盖它(如果需要)。

        7
  •  1
  •   StaceyGirl    6 年前

    如果我的编译器设置为32位, size_t 只是的typedef unsigned int . 如果我的编译器设置为64位, 西泽特 只是的typedef unsigned long long .

        8
  •  -3
  •   who    16 年前

    大小是指针的大小。

    因此,在32位或通用的ILP32(整数、长、指针)中,模型大小为32位。 在64位或者普通的lp64(long,pointer)中,模型大小为64位(整数仍然是32位)。

    还有其他的模型,但这些模型是G++使用的(至少在默认情况下是这样)