编译器的Bug还是误解?或者对短裤的运算符

本文关键字:运算符 或者 误解 Bug 编译器 | 更新日期: 2023-09-27 18:16:35

我有一行代码,在VS2015中给我一个警告消息(CS0675),但不是在2013年。

shortValue |= (short)anEnum;

警告CS0675位或操作符在符号扩展操作数上使用;首先考虑转换为较小的无符号类型。编译器隐式扩展和符号扩展变量,然后使用位或运算的结果值。这可能导致意想不到的行为。

显然,现在的情况是enum和short类型被扩展为int类型,应用or操作符,然后将结果赋值给short类型。

如果我将代码更改为shortValue = shortValue | (short)anEnum;,我会得到一个编译器错误CS0266。但是按位或应该对短裤有效(我相信在这两种情况下)。如果我把鼠标悬停在|上,它显示为一个int操作符,我错过了什么,或者我应该报告这是一个bug?

PS:我知道我可以通过使用=而不是|=来消除警告/错误,并将结果转换为短。

编译器的Bug还是误解?或者对短裤的运算符

如果你看一下c#规范(特别是在"整数逻辑运算符"中),你会发现只有int, uint, long, ulong的逻辑或运算符定义:

int operator |(int x, int y);
uint operator |(uint x, uint y);
long operator |(long x, long y);
ulong operator |(ulong x, ulong y);

另外,在Bit twiddling中:警告CS0675是什么意思?Eric Lippert说:

" int, uint, longulong上定义了位或运算符"

运算符对short有效,但仅在短值可以扩展到int的意义上有效。然而,该操作符的返回值(至少)是int

所以,从技术上讲,根据规范,这似乎不是一个bug,因为使用|=确实将带符号的值扩展为int,这会给出警告,而常规的|会导致int,需要将其转换为分配给short

然而,由于编译器实际上可以知道两个操作数最初都是short,它们都扩展到int,并且结果最终将存储回short,因此操作数扩展并不重要。从int转换到short时,扩展将丢失。

所以,要么VS2013编译器的警告比VS2015更聪明,要么VS2015修复了一个错误,并在VS2013失败的地方发出警告。只有编译器背后的人可以回答这个问题,但我认为这确实是一个错误(编辑:它是)。