当我使用size_t类型(或无符号长整数)进行算术运算时,我应该多么小心地使用类型文字来装饰整数常量。例如,
size_t a = 1111111;
if (a/2 > 0) ...;
当编译器进行除法时会发生什么?它将2视为整数还是无符号整数?如果是前者,那么(unsigned int)/(int)的结果类型是什么?
我是否应该小心写'你'文字
if (a/2u > 0) ...;
for (a=amax; a >= 0u; a -= 3u) ...;
或编译器会正确猜测我想使用无符号整数运算吗?
答案 0 :(得分:6)
2
确实被视为int
,然后将其隐式转换为size_t
。在混合操作size_t / int
中,无符号类型"胜出"假设无符号类型至少与签名类型一样宽,则签名类型将转换为无符号类型。结果是无符号的,即您的情况为size_t
。 (有关详细信息,请参阅Usual arithmetic conversions。)
最好将其写为a / 2
。没有后缀,没有类型演员。保持代码尽可能与类型无关。类型名称(和后缀)属于声明,而不是语句。
答案 1 :(得分:3)
size_t
是无符号整数。 2
始终为int
类型。所以编译器实际上解释了这样的表达式:
a/(size_t)2 > (size_t)0
(>
运算符或任何关系运算符的结果总是类型int
,作为该组运算符的特例。)
我是否应该小心写'你'文字
一些编码标准,尤其是MISRA-C,会让您这样做,以确保代码中不存在隐式类型促销。隐式促销或转化 非常危险,它们是C语言中的一个缺陷。
对于您的具体情况,隐式促销没有真正的危险。但是有些情况下会使用小整数类型,并且由于隐式类型提升,您最终可能会无意中更改签名。
明确绝不会有任何伤害,尽管在代码中为每个文字写一个u
后缀可能会降低可读性。
现在你作为C程序员处理类型推广危险的真正必须做的是学习整数提升和通常的算术转换是如何工作的(here's some example on the topic)。可悲的是,有许多C程序员没有,包括退伍军人。结果是微妙的,但有时是严重的错误。特别是当使用诸如移位之类的逐位运算符时,签名的改变可能会调用未定义的行为。
这些规则可能有些棘手,因为它们并非真正合理或一致地表现。但是在你详细了解这些规则之前,你必须明确表达类型。
编辑:为了挑剔,实际上没有指定size_t
的大小,所有标准都说它必须足够大以至少保持值65535(2字节)。因此理论上,size_t
可能等于unsigned short
,在这种情况下,促销会变得非常不同。但在实践中,我怀疑这种情况是否有任何意义,因为我不相信存在size_t
小于unsigned int
的任何实现。
答案 2 :(得分:0)
C ++和C在评估带有两个参数的运算符时将签名类型提升为无符号类型,其中一个参数是无符号类型。
因此,文字2将转换为无符号类型。
就个人而言,我认为最好将升级保留给编译器而不是明确:如果您的代码被重构并且a
成为签名类型,则a / 2u
会导致a
被提升为无条件类型,可能带来灾难性的后果。
答案 3 :(得分:0)
size_t sz = 11;
sz / 2 = 5
sz / (-2) = 0
为什么?
sz
被视为unsigned int,因为size不能为负数。使用无符号int
和int
进行算术运算时,int
会变为unsigned int
。
来自" CS dummies"