对于C中的典型循环,可以写:
for (unsigned int i = 0; i < 10; i++) {}
但是,有些人建议改为使用size_t
:
for (size_t i = 0; i < 10; i++) {}
因为unsigned int
在索引增长超过UINT_MAX
时可能会失败。
虽然我理解这一点,但有时我需要将size_t
与其他固定长度类型(例如uint32_t
)一起使用,或者将一些size_t
写入网络。如果处理不当,这些操作容易出错。我认为同样适用于其他整数类型,例如ssize_t
,socklen_t
等。
处理这些不同整数和大小类型的混合并在必要时安全转换它们的正确方法是什么?
EDIT。关于类型长度的另一个问题是在printf
语句中打印其值。 size_t
有自己的格式说明符z
。并非所有整体类型都有这种奢侈。如果printf
在变量上接受typeof
运算符,可能会更容易,但不幸的是,它不会。
答案 0 :(得分:1)
您可以将目标/源整数类型的范围与大小类型的范围进行比较。数字应自动提升到足够大的类型进行比较(假设不涉及负数)。
size_t
的最大值在stdint.h
中定义(自C99起):SIZE_MAX
。固定宽度整数类型的限制也可以在该标题中找到,例如UINT64_MAX
。
整数类型的范围在limits.h
中定义:例如ULONG_MAX
。
供参考:
答案 1 :(得分:0)
规则摘要如下:
http://en.cppreference.com/w/c/language/types
总之,固定长度类型是唯一可以并且应该依赖的大小类型。类型之间存在相对限制(例如long永远不会短于int),而整数类型具有强制 minumum 长度(例如int保证至少为16位)。 / p>
因此,对于网络通信,您需要固定长度类型(以网络字节顺序进行传输和接收)或编码协议(例如谷歌协议缓冲区)。
答案 2 :(得分:0)
处理这些不同整数和大小类型的混合并在必要时安全转换它们的正确方法是什么?
是的,这具有挑战性和广泛性 以下是一些有用但尚未完成的公理。有些有限制:
对数组size_t
索引使用[]
。 (如果代码知道索引范围很小,可以使用较小的类型。)
使用size_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.
当两种类型具有相同的符号或已知有符号类型比无符号类型更宽时,只需编码而不使用强制转换
if (sg < un)
否则单独处理潜在负值
if (sg < 0 || sg < un)
通常安全转换,测试范围:
// typea --> typeb
if (vara < typeb_MIN || vara > typeb_MAX) Handle_Error()
else varb = vara;
避免将typea
投射到typeb
,除非代码必须转换为typeb
。而是乘以((typeb)1)
。这样可以防止截断(也见前文)
(typeb) vara // avoid
((typeb) 1) * vara
当打印和代码在类型的范围/宽度上不清楚时,请使用最大宽度类型
ssize_t ssz = foo();
printf("%jd\n", ((intmax_t)1) * ssz);
printf("%lld\n", 1LL * ssz);
计算2D数组的字节大小时,先乘以size_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 long
intmax_t
unsigned char
,unsigned short
,unsigned
,unsigned long
unsigned long long
uintmax_t
char
已签名或未签名。 size_t
(已签名)ptrdiff_t
int8_t
,uint32_t
以及可能令人惊讶的uint24_t
。 int_least8_t
,...,uint_least64_t
。 int_fast8_t
,...,uint_fast64_t
。 wchar_t
,wint_t
,sig_atomic_t
,max_align_t
,...,...,...等等。其中许多类型只是其他类型的typedef
。其他像int
和long
可能具有相同的范围,但保持其独特的类型。