我正在尝试运行此程序(来自Wikipedia):
/**
Multiply two numbers in the GF(2^8) finite field defined
by the polynomial x^8 + x^4 + x^3 + x + 1.
*/
ubyte gMul(ubyte a, ubyte b) pure nothrow {
ubyte p = 0;
foreach (immutable ubyte counter; 0 .. 8) {
p ^= -(b & 1) & a;
auto mask = -((a >> 7) & 1);
// 0b1_0001_1011 is x^8 + x^4 + x^3 + x + 1.
a = (a << 1) ^ (0b1_0001_1011 & mask);
b >>= 1;
}
return p;
}
void main() {
import std.stdio, std.conv;
enum width = ubyte.max + 1, height = width;
auto f = File("rijndael_finite_field_multiplication.pgm", "wb");
f.writefln("P5\n%d %d\n255", width, height);
foreach (immutable y; 0 .. height)
foreach (immutable x; 0 .. width) {
immutable char c = gMul(x.to!ubyte, y.to!ubyte);
f.write(c);
}
}
当我这样做时,我得到此错误:
test.d(12): Error: cannot implicitly convert expression (cast(int)a << 1 ^ 283 & mask) of type int to ubyte
Failed: ["dmd", "-v", "-o-", "test.d", "-I."]
我不清楚如何解决此问题。有任何想法吗?
如果看到“无法隐式转换”错误,则一种解决方法通常是使用cast
运算符进行显式转换:
// before
a = (a << 1) ^ (0b1_0001_1011 & mask);
// after
a = cast(ubyte)((a << 1) ^ (0b1_0001_1011 & mask));
注意cast(ubyte)
与()
整个表达式周围。
那应该可以解决您的问题,但让我也解释一些其他问题...
test.d(12):错误:无法将int类型的表达式(cast(int)a << 1 ^ 283和掩码)隐式转换为ubyte
在此错误消息中,您注意到编译器cast(int)
在之前插入了a
。这在大多数算术中都会发生,因为D继承了C的整数提升规则:https : //www.bing.com/search?q = c+integer+promotion & pc = MOZI & form = MOZLBR任何算术在D发生之前都被强制转换为int,就像在C中
但是,D与C在重要方面不同:D禁止缩小隐式转换,除非编译器可以单独在表达式中证明表达式的值肯定适合该类型。
因此,像文字一样4 + 10
,编译器知道它大于或等于零,但小于256,因此适合a ubyte
,不需要显式强制转换。
但是,如果您这样做了ubyte a; ubyte b; ubyte c = a + b;
,编译器将无法再单独在此表达式中证明它-a + b
可能在0(最小值,0 + 0)到510(最大值,255 + 255)之间。所以它可能适合……但可能不适合。因此,编译器将要求您显式转换它。
但是,请检查一下:ubyte a, b; ubyte c = a & 0xf + b & 0xf0;
它将编译。为什么?因为编译器可以看到这些位掩码并了解它会更改可能的值范围。一旦掩盖了这些值,它就会限制它们并且这些可能值的总和就适合了……因此不需要强制转换。
这里的想法是,如果通过将可能的值填充到ubyte
(或其他小的类型)中来丢弃可能的值,则编译器希望确保您知道它并做出有意识的决定。因此,如果有一点点机会掉线,就需要演员表。(另一方面,C不需要强制转换,因为它只会很高兴地丢弃字节。)
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句