Error: cannot implicitly convert expression ... of type int to ubyte
Error: cannot implicitly convert expression ... of type int to ubyte
我正在尝试 运行 这个程序 (from 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."]
我不清楚如何解决这个问题。有什么想法吗?
如果您看到 "cannot implicitly convert" 错误,一种解决方法通常是使用 cast
运算符显式转换:
// before
a = (a << 1) ^ (0b1_0001_1011 & mask);
// after
a = cast(ubyte)((a << 1) ^ (0b1_0001_1011 & mask));
注意整个表达式周围的 cast(ubyte)
和 ()
。
这应该可以解决您的问题,但让我再解释几件事...
test.d(12): Error: cannot implicitly convert expression (cast(int)a << 1 ^ 283 & mask) of type int to ubyte
在此错误消息中,您注意到编译器在 a
之前插入了一个 cast(int)
。这在大多数算术中都会发生,因为 D 继承了 C 的整数提升规则:https://www.bing.com/search?q=c+integer+promotion&pc=MOZI&form=MOZLBR 任何算术在 D 中发生之前都会被强制转换为 int,就像在 C 中一样。
但是,D 在一个重要方面不同于 C:它禁止缩小隐式转换,除非编译器可以证明,仅在表达式中,表达式的值绝对适合这种类型。
所以,像文字 4 + 10
这样的东西,编译器知道它大于或等于零,但小于 256,因此适合 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 不需要强制转换,因为它会很高兴地删除字节。)
我正在尝试 运行 这个程序 (from 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."]
我不清楚如何解决这个问题。有什么想法吗?
如果您看到 "cannot implicitly convert" 错误,一种解决方法通常是使用 cast
运算符显式转换:
// before
a = (a << 1) ^ (0b1_0001_1011 & mask);
// after
a = cast(ubyte)((a << 1) ^ (0b1_0001_1011 & mask));
注意整个表达式周围的 cast(ubyte)
和 ()
。
这应该可以解决您的问题,但让我再解释几件事...
test.d(12): Error: cannot implicitly convert expression (cast(int)a << 1 ^ 283 & mask) of type int to ubyte
在此错误消息中,您注意到编译器在 a
之前插入了一个 cast(int)
。这在大多数算术中都会发生,因为 D 继承了 C 的整数提升规则:https://www.bing.com/search?q=c+integer+promotion&pc=MOZI&form=MOZLBR 任何算术在 D 中发生之前都会被强制转换为 int,就像在 C 中一样。
但是,D 在一个重要方面不同于 C:它禁止缩小隐式转换,除非编译器可以证明,仅在表达式中,表达式的值绝对适合这种类型。
所以,像文字 4 + 10
这样的东西,编译器知道它大于或等于零,但小于 256,因此适合 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 不需要强制转换,因为它会很高兴地删除字节。)