Protocol Buffer 中的 uint 转换

uint casting in Protocol Buffer

我在Protocol Buffers中定义了一条Color消息如下:

message Color {
    fixed32 rgb = 1;
}

我在 C# 语言中定义 Color 如下:

byte red    = pixels[4 * index + 0];
byte green  = pixels[4 * index + 1];
byte blue   = pixels[4 * index + 2];
byte alpha  = pixels[4 * index + 3];
Color color = new Color
{
    Rgb = (uint)((red << 16) | (green << 8) | blue)
};

担心下面的操作是否有效:

Rgb = (uint)((red << 16) | (green << 8) | blue)

请注意,如果没有 uint 转换,程序会抛出编译错误。

是的,完全正确。这里发生的是 byte return int 上的移位运算符 (<< / >>)。因为……原因。实际上,几乎所有运算符都在bytereturnint上-两个[=14的"or"(|) =] 值是 int.

编译器不喜欢 盲目地 让你将 int 转换为 uint,所以它只是想让你承认你是这样做,这就是您添加的 (uint) 所做的。

由于我们知道您只填充了前 24 位,我们知道该值始终为正数,因此它始终 是一个可以安全地存储的正整数转换为无符号 (uint).

如果您要填充所有 32 位,有可能最终值为负数,但默认情况下 C#编译器在 "unchecked" 模式下工作,所以:它不在乎。它会愉快地将负数 int 转换为 uint。例如,-8 变为 4294967288。但是,作为命令行选项,可以启用 "checked" 模式 - 在这种情况下,您将获得 OverflowException。为避免这种情况,可以使用 unchecked 修饰符明确地告诉它 不关心,例如:

int i = -8;
uint u = unchecked((uint)i);

unchecked
{
    int i = -8;
    uint u = (uint)i;
    // ...
}

但是,unchecked 的这种用法 几乎从不需要 。人们更常见的是在他们 关心溢出的地方添加偶尔的 checked 修饰符。

所以总结一下:是的,你所拥有的很好。