2016-01-02 59 views
2
size_t a; 
off_t b; 
... 
if(b<a) ... 

正如预期的那样,由于off_t是signed并且size_t是无符号的,因此编译器在此处发出“signed vs unsigned comparsion”警告。有没有办法做这样的比较,在任何平台上正确工作,而不使用intmax_t/uintmax_t和预处理器条件指令?
签名与无符号比较

无论sizeof(size_t)和sizeof(off_t)等于多少,它都应该可以工作。他们可能有任何值,例如:

sizeof(size_t)=4, sizeof(off_t)=8 (regular modern 32bit unix) 
sizeof(size_t)=4, sizeof(off_t)=4 (older system) 
sizeof(size_t)=8, sizeof(off_t)=4 (some 64bit system with 32bit filesystem support) 

如果我只是一个强制转换到另一个,可能会出现数据丢失和不正确的结果。

编辑要清楚:b的负值不是问题,因为负b很容易检测到(如果(b < 0))并且始终小于ANY的无符号a值。问题是两个这样的类型的正值的比较,我不知道什么类型有更大的宽度。

EDIT2它与“比较off_t和ssize_t与其他类型”不重复,因为该问题是关于比较具有不同位宽的签名类型,这是关于有符号和无符号类型;在这个问题中的第一个答案也没有回答这个问题,因为答案是关于两个相同大小的类型,这里有两个未知大小的类型; 也是这个问题不只是comparsion,它也是关于避免警告

+0

数据丢失如何发生?两者之间的区别仅仅是符号位。 – TheRealChx101

回答

2
if(b < 0 || (b <= SIZE_MAX && (size_t)b < a)) 

应该可以在所有情况下工作。

如果b是负数,那么显然它小于a,因为a不能为负数(因为size_t是无符号的)。

如果bSIZE_MAX大,那么它显然大于a因为a不能超过SIZE_MAX更大。

否则,它们都在size_t的有效范围内,因此只需将它们作为size_t s即可。

+0

upv,我准备发表完全相同的表达式 – ouah

+1

,正如在(为什么?)删除注释中所说的那样,它仍然会为b <= SIZE_MAX生成签名/未签名警告;它现在似乎不是一个错误,但我想编译它与 - 错误标志,所以我searchign的方式来删除这个警告在所有 – firk

+0

@immibis它似乎没有警告的条件是(b <0 ||(!(b&〜 ((off_t)SIZE_MAX))&&(size_t)b firk

0

的问题是,“任何价值”包括消极的,在这种情况下,你必须应用特殊的代码来处理它,因为底层机器没有。

如果您知道您的值保证非负,那么只需将它们转换为与最大操作数匹配的无符号类型即可。