size_t除以int类型转换规则

size_t divided by int type conversion rules

本文关键字:类型转换 规则 int 除以 size      更新时间:2023-10-16

当我使用size_t类型(或无符号长(进行算术运算时,用类型文字修饰整数常量时应该多么小心。例如,

size_t a = 1111111;
if (a/2 > 0) ...;

编译器进行除法运算时会发生什么?它将2视为整数还是无符号整数?如果是前者,那么(unsigned int(/(int(的结果类型是什么?

我应该一直小心地写"u"字吗

if (a/2u > 0) ...;
for (a=amax; a >= 0u; a -= 3u) ...;

或者编译器会正确地猜测我想使用无符号整数的运算吗?

2确实被视为int,然后隐式转换为size_t。在混合运算size_t / int中,无符号类型"获胜",有符号类型转换为无符号类型,假设无符号类型至少与有符号类型一样宽。结果是无符号的,即在您的情况下为size_t。(有关详细信息,请参阅常用算术转换(。

最好把它写成a / 2。没有后缀,没有类型转换。尽可能保持代码的类型独立性。类型名称(和后缀(属于声明,而不是语句。

  • C标准保证size_t是一个无符号整数
  • 文字2的类型始终为int
  • "通常的artihmetic转换保证,每当在二进制运算中使用大小相同的无符号整数和有符号整数("秩"(作为操作数时,有符号操作数就会转换为无符号类型

所以编译器实际上是这样解释这个表达式的:

a/(size_t)2 > (size_t)0

(不过,>运算符或任何关系运算符的结果总是int类型,这是该组运算符的特殊情况。(

我应该一直小心地写"u"字吗

一些编码标准,尤其是MISRA-C,会让你这样做,以确保代码中不存在隐含的类型提升。隐式提升或转换非常危险的,它们是C语言中的一个缺陷。

对于你的具体情况,隐性晋升并没有真正的危险。但是,在某些情况下,使用小整数类型时,由于隐式类型提升,您可能会无意中更改签名性。

显式从来没有任何害处,尽管在代码中的每个文字上写一个u后缀可能会降低可读性。

现在,作为一名C程序员,要处理类型提升的危险,你真正必须做的是学习整数提升和常见的算术转换是如何工作的(这里有一些关于该主题的例子(。遗憾的是,有很多C程序员不这样做,包括资深程序员。结果是微妙的,但有时是关键的错误。特别是在使用移位等位运算符时,其中签名性的更改可能会调用未定义的行为。

这些规则可能有点难学,因为它们的行为并不理性或始终如一。但是,在详细了解这些规则之前,您必须明确类型。


EDIT:挑剔的是,size_t的大小实际上并没有指定,标准只说它必须足够大,至少可以容纳65535(2字节(的值。因此,理论上,size_t可以等于unsigned short,在这种情况下,晋升会大不相同。但在实践中,我怀疑这种情况是否有任何意义,因为我不认为存在size_t小于unsigned int的任何实现。

C++和C在计算类似除法的运算符时都将有符号类型提升为无符号类型,除法需要两个参数,其中一个参数是无符号类型。

因此,文字2将被转换为无符号类型。

就我个人而言,我认为最好把升级留给编译器,而不是显式:如果你的代码被重构,a变成了一个有符号的类型,那么a / 2u会导致a被升级成一个无符号类型,这可能会带来灾难性的后果。

size_t sz = 11;
sz / 2 = 5
sz / (-2) = 0

为什么?sz被视为无符号int,因为大小不能为负数。当用无符号intint进行算术运算时,int变为unsigned int

来自"CS假人">