C 如何正确使用size\u t和其他整数类型?

C 如何正确使用size\u t和其他整数类型?,c,types,type-conversion,size-t,C,Types,Type Conversion,Size T,对于C中的典型循环,可以编写: for (unsigned int i = 0; i < 10; i++) {} 因为unsigned int可能会在索引增长超过UINT\u MAX时失败 虽然我理解这一点,但有时我需要将size\u t与其他固定长度类型(如uint32\u t)一起使用,或者将一些size\u t写入网络。如果处理不当,这些操作很容易出错。我认为这同样适用于其他整数类型,例如ssize\u t,socklen\u t,等等 处理这些不同整数和大小类型的混合并在必要时

对于C中的典型循环,可以编写:

for (unsigned int i = 0; i < 10; i++) {}
因为
unsigned int
可能会在索引增长超过
UINT\u MAX
时失败


虽然我理解这一点,但有时我需要将
size\u t
与其他固定长度类型(如
uint32\u t
)一起使用,或者将一些
size\u t
写入网络。如果处理不当,这些操作很容易出错。我认为这同样适用于其他整数类型,例如
ssize\u t
socklen\u t
,等等

处理这些不同整数和大小类型的混合并在必要时安全地转换它们的正确方法是什么


编辑。关于类型长度的另一个问题是在
printf
语句中打印其值
size\u t
有自己的格式说明符
z
。并不是所有的整体类型都有这种奢侈。如果
printf
接受变量上的
typeof
运算符,可能会更容易些,但不幸的是,它没有接受。

规则摘要如下:

总之,固定长度类型是唯一可以而且应该依赖于大小的类型。类型之间有相对的限制(例如long永远不小于int),整型类型有强制的最小长度(例如int至少保证为16位)


因此,对于网络通信,您需要固定长度类型(以网络字节顺序传输和接收)或编码协议(例如google协议缓冲区)。

您可以将目标/源整数类型的范围与大小类型的范围进行比较。数字应自动升级到足够大的类型,以便进行比较(假设不涉及负数)

size\u t
的最大值在
stdint.h
中定义(自C99起):
size\u MAX
。固定宽度整数类型的限制也可以在该标题中找到,例如,
UINT64_MAX

整数类型的范围在
limits.h
中定义:例如
ULONG_MAX

供参考:

处理这些不同整数和大小类型的混合并在必要时安全地转换它们的正确方法是什么

是的,这是一项挑战性和广泛性的工作。
下面是一些有帮助的公理,但还远未完成。有些有局限性:

  • 对数组
    []
    索引使用
    size\t
    。(如果代码知道索引范围很小,可以使用较小的类型。)

  • 注意使用
    size\u t

    size_t i,a,b;
    // for (i = a; i-1 < b; i++) { // `i-1` may wrap
    for (i = a; i < b + 1; i++) { // `b+1u` may wrap but far less likely.
    
  • 如果打印和编码在字体的范围/宽度上不清晰,请使用最大宽度字体

    ssize_t ssz = foo();
    printf("%jd\n", ((intmax_t)1) * ssz);
    printf("%lld\n", 1LL * ssz);
    
  • 在计算2D数组的字节大小时,先乘以
    大小\u t
    类型

    p = malloc(width * height * sizeof *p);   // potential overflow in width * height
    p = malloc(sizeof *p * width * height);   
    

  • 注意:一些C整数类型

    • 已签名:
      Signed char
      short
      int
      long
      long
      intmax\t
    • 无符号:
      Unsigned char
      Unsigned short
      Unsigned
      Unsigned long
      无符号long
      uintmax\t
    • 另外,
      char
      可以是有符号的,也可以是无符号的
    • 特殊:(未签名)
      size\u t
      (签名)
      ptrdiff\u t
    • 精确宽度(可选)示例:
      int8\u t
      uint32\u t
      以及可能令人惊讶的
      uint24\u t
    • 最小宽度(至少8种类型)
      int至少8\u t
      ,…,
      uint至少64\u t
    • 快速宽度(至少8种)
      int\u fast8\u t
      ,…,
      uint\u fast64\u t
    • 另外,
      wchar\u t
      wint\u t
      sig\u-atomic\u t
      max\u-align\u t
      。。。等等
    • 位字段

    这些类型中的许多只是其他类型的
    typedef
    s。其他如
    int
    long
    可能具有相同的范围,但保持其独特的类型。

    这非常有帮助:-Wconversion(警告可能改变值的隐式转换)请参阅:[精确宽度整数类型是可选的]。对于(极端)可移植性,不要依赖于它们。@pmg我想有时候我们对不使用它们没有发言权:
    manhtons
    @Cyker
    htons()
    在C标准中没有描述:它在极端可移植性之外。@pmg我明白了。但是,所有使用
    hton
    的网络例程都不属于
    极端可移植性
    范畴,我打赌其中有一些重要的。因此,上述问题仍然是一个重要的实际问题。我不同意你的总结。您可以依赖内置类型的大小。特别是,
    int
    的范围保证至少在-32767到32767之间。在这种情况下,我的措辞是草率的。我会把它修好的。@fuzzxl我想我今天早上起床的姿势不对。我把这个问题当作C++问题来读。谢谢你修正了答案。限制页+1。最好还包括由常用库定义的类型,但它们不是cpp引用。
    if (sg < 0 || sg < un)
    
    // typea --> typeb
    if (vara < typeb_MIN || vara > typeb_MAX) Handle_Error()
    else varb = vara;
    
    (typeb) vara // avoid
    ((typeb) 1) * vara
    
    ssize_t ssz = foo();
    printf("%jd\n", ((intmax_t)1) * ssz);
    printf("%lld\n", 1LL * ssz);
    
    p = malloc(width * height * sizeof *p);   // potential overflow in width * height
    p = malloc(sizeof *p * width * height);