C# 数值常量

C# numeric constants

提问人:Rob Walker 提问时间:9/4/2008 最后编辑:Adi LesterRob Walker 更新时间:6/3/2013 访问量:13150

问:

我有以下 C# 代码:

byte rule = 0;
...
rule = rule | 0x80;

这会产生错误:

无法将类型“int”隐式转换为“byte”。存在显式转换(是否缺少强制转换?

[更新:问题的第一个版本是错误的......我误读了编译器输出]

添加强制转换并不能解决问题:

rule = rule | (byte) 0x80;

我需要把它写成:

rule |= 0x80;

这看起来很奇怪。为什么操作员与操作员有什么不同?|=|

有没有其他方法可以告诉编译器将常量视为字节?


@Giovanni Galbo :是的,也不是。该代码处理外部设备中闪存的编程,并在逻辑上表示单个字节的存储器。我可以稍后施放它,但这似乎更明显。我想我的 C 传统表现得太多了!

@乔纳森·霍兰德(Jonathon Holland):“as”语法看起来更整洁,但不幸的是似乎不起作用......它产生:

as 运算符必须与引用类型或可为 null 的类型(“byte”是不可为 null 的值类型)一起使用

C# 强制转换

评论


答:

1赞 John Rutherford 9/4/2008 #1

看起来你可能只需要以丑陋的方式去做:http://msdn.microsoft.com/en-us/library/5bdb6693.aspx

34赞 Eric Z Beard 9/4/2008 #2

C# 没有 byte 的文本后缀。u = uint,l = long,ul = ulong,f = float,m = 十进制,但没有字节。你必须铸造它。

评论

2赞 blizpasta 8/20/2010
用户:它没有定义它 C# 语言规范。这里有一个例子:msdn.microsoft.com/en-us/library/5bdb6693(VS.80).aspx 您可以声明并初始化字节变量,如下所示: byte myByte = 255;在前面的声明中,整数文字 255 从 int 隐式转换为 byte。如果整数文字超出字节范围,则会发生编译错误。
9赞 FlySwat 9/4/2008 #3

您要查找的术语是“Literal”,不幸的是 C# 没有字节文本。

下面是所有 C# 文本的列表。

3赞 grom 9/4/2008 #4

根据 ECMA 规范,第 72 页没有字节文字。仅包含以下类型的整数文本:int、uint、long 和 ulong。

0赞 Peter Meyer 9/4/2008 #5

不幸的是,你唯一的办法就是按照你的方式去做。没有后缀将文本标记为字节。这 |运算符不像赋值(即初始化)那样提供隐式转换。

11赞 jmatthias 9/4/2008 #6

这工作原理:

rule = (byte)(rule | 0x80);

显然,“规则 |0x80“返回一个 int,即使您将 0x80定义为”const byte 0x80”。

6赞 David J. Sokol 9/4/2008 #7
int rule = 0;
rule |= 0x80;

http://msdn.microsoft.com/en-us/library/kxszd0kx.aspx这 |运算符是为所有值类型定义的。我认为这将产生预期的结果。“|=”运算符是 or then assign 运算符,它只是 rule = rule |0x80。

C# 的一个更漂亮的事情是,它允许你做一些疯狂的事情,比如滥用值类型,只是根据它们的大小。'int' 与字节完全相同,但如果您尝试同时使用它们,编译器将抛出警告。简单地坚持使用一个(在本例中为 int)效果很好。如果您担心 64 位就绪情况,可以指定 int32,但所有 int 都是 int32,即使在 x64 模式下运行也是如此。

评论

0赞 Eloff 5/5/2010
正如你所说,所有的 int 都是 int32,语言(或 CLR)规范不是有这个保证吗?
4赞 TheXenocide 7/2/2012
int 是 Int32 的 C# 别名,绝对不等同于字节。JIT编译器是平台感知的,所以我们不需要这样做。本机字大小、寻址和针对各种本机基元的操作效率更有可能涉及它如何在底层系统中分配托管数据(包括“基元”)。考虑到可以为 .NET Micro 和 .NET CF(面向手机的 ARM 和面向 XBox 360 的 PowerPC)编译相同的代码。这些系统甚至可以用不同的字节序来表示它们的数字,这对二进制运算有重大影响。
0赞 jfs 9/4/2008 #8

显然,“规则 | 0x80' 返回一个 int,即使你 将0x80定义为“const byte 0x80”。

我认为规则是像这样的数字0x80默认为 int,除非您包含文字后缀。因此,对于表达式,结果将是一个 int,因为 0x80 是一个 int,并且规则(这是一个字节)可以安全地转换为 int。rule | 0x80

评论

0赞 Ethan 6/1/2012
这是不正确的。即使将 0x80 转换为字节,运算符也会给你一个 int。试着:看看我的意思。但是,您可以将整个操作括在括号中,并将其全部转换为字节:|rule = rule | (byte)0x80;rule = (byte)(rule | 0x80);
0赞 Bruce Bowman 1/28/2013 #9

根据 C 标准,字节在表达式中总是提升为 int,甚至是常量。但是,只要这两个值都是 UNSIGNED,高阶位就会被丢弃,因此操作应返回正确的值。

同样,浮动提升到双倍,等等。

拉出K&R的副本。一切都在那里。

2赞 arx 6/3/2013 #10

差不多五年过去了,没有人真正回答过这个问题。

有几个答案声称问题在于缺少字节文字,但这无关紧要。如果计算,则结果为 类型。即使“b”是字节的文字后缀,其类型仍然是 。(byte1 | byte2)int(23b | 32b)int

接受的答案链接到一篇 MSDN 文章,该文章声称为所有整数类型定义,但事实并非如此。operator|

operator|未定义,因此编译器使用其通常的重载解析规则来选取 上定义的版本。因此,如果要将结果分配给 a,则需要将其强制转换:byteintbyte

rule = (byte)(rule | 0x80);

问题仍然存在,为什么有效?rule |= 0x80;

因为 C# 规范具有复合赋值的特殊规则,允许您省略显式转换。在复合赋值中,规则是:x op= y

如果所选运算符是预定义运算符,如果所选运算符的返回类型可显式转换为 X 的类型,并且 y 隐式转换为 x 的类型或运算符是移位运算符,则运算的计算结果为 ,其中 T 是 x 的类型,但 x 只计算一次。x = (T)(x op y)