size_t除以int类型转换规则

Joh*_*ith 3 c c++ type-conversion literals

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

size_t a = 1111111;
if (a/2 > 0) ...;
Run Code Online (Sandbox Code Playgroud)

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

我应该经常小心地写'你'文字

if (a/2u > 0) ...;
for (a=amax; a >= 0u; a -= 3u) ...;
Run Code Online (Sandbox Code Playgroud)

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

AnT*_*AnT 6

2确实被视为一个int,然后被隐式转换为size_t.在混合操作中size_t / int,无符号类型"wins"和签名类型将转换为无符号类型,假设无符号类型至少与签名类型一样宽.结果是未签名的,即size_t在您的情况下.(有关详细信息,请参阅常用算术转换).

把它写成是一个更好的主意a / 2.没有后缀,没有类型演员.保持代码尽可能与类型无关.类型名称(和后缀)属于声明,而不是语句.


Lun*_*din 5

  • C 标准保证这size_t是一个无符号整数。
  • 文字2始终是类型int。
  • “通常的算术转换保证,每当相同大小(“等级”)的无符号和有符号整数用作二进制运算中的操作数时,有符号操作数都会转换为无符号类型。

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

a/(size_t)2 > (size_t)0
Run Code Online (Sandbox Code Playgroud)

(但是,作为该组运算符的特殊情况,运算符或任何关系运算符的结果>始终是类型。)int

我应该总是小心地写“u”文字吗

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

对于您的具体情况,隐性促销并不存在真正的危险。但在某些情况下,使用小整数类型时,您可能会由于隐式类型提升而导致符号性无意更改。

尽管u为代码中的每个文字编写后缀可能会降低可读性,但明确地永远不会有任何坏处。

现在,作为一名 C 程序员,为了应对类型提升危险,您真正必须做的是了解整数提升和常见算术转换的工作原理(这里是有关该主题的一些示例)。遗憾的是,有很多 C 程序员不这样做,包括退伍军人。结果是微妙的,但有时会出现严重的错误。特别是在使用按位运算符(例如移位)时,符号的更改可能会引发未定义的行为。

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


编辑:要挑剔,实际上没有指定 的大小size_t,所有标准都说它必须足够大以至少容纳值 65535 (2 个字节)。因此从理论上讲,size_t可能等于unsigned short,在这种情况下,促销结果会完全不同。但实际上,我怀疑这种情况是否有任何意义,因为我不相信存在任何size_t小于 的实现unsigned int。