我正在玩整数数组散列以及从表示到另一个的不同方式。我最终得到了以下内容:
void main(string[] args) {
import std.algorithm, std.array, std.conv, std.stdio, std.digest.md;
union hashU {
ubyte[] hashA;
int[] hashN;
};
hashU a;
auto md5 = new MD5Digest();
a.hashN = [1, 2, 3, 4, 5];
/* Using an union, no actual data conversion */
md5.put( a.hashA );
auto hash = md5.finish();
writeln(hash);
// [253, 255, 63, 4, 193, 99, 182, 232, 28, 231, 57, 107, 18, 254, 75, 175]
/* Using a cast... Doesn't match any of the other representations */
md5.put( cast(ubyte[])(a.hashN) );
hash = md5.finish();
writeln(hash);
// [254, 5, 74, 210, 231, 185, 139, 238, 103, 63, 159, 242, 45, 80, 240, 12]
/* Using .to! to convert from array to array */
md5.put( a.hashN.to!(ubyte[]) );
hash = md5.finish();
writeln(hash);
// [124, 253, 208, 120, 137, 179, 41, 93, 106, 85, 9, 20, 171, 53, 224, 104]
/* This matches the previous transformation */
md5.put( a.hashN.map!(x => x.to!ubyte).array );
hash = md5.finish();
writeln(hash);
// [124, 253, 208, 120, 137, 179, 41, 93, 106, 85, 9, 20, 171, 53, 224, 104]
}
我的问题如下:演员是做什么的?我原以为它要像.to一样做!或联盟技巧,但似乎并非如此。
答案 0 :(得分:4)
我认为Colin Grogan说得对,但他的措辞有点令人困惑。
使用union,只需重新解释数组,根本不会进行任何计算/计算。重新解释int[]
的指针和长度以引用ubyte
元素。之前:5个整数,之后:5个字节。
演员比这更聪明:它调整数组的长度,使其引用与以前相同的内存。之前:5个整数,之后:20个字节(5 * int.sizeof
/ ubyte.sizeof
= 5 * 4/1 = 20)。
union和cast都将int的字节重新解释为ubytes。也就是说,int值1将产生4 ubytes:0,0,0,1或1,0,0,0,具体取决于endianess。
to
变体将每个元素转换为新元素类型。之前:5个整数,之后:5个ubytes,其值与整数相同。如果其中一个int不能转换为ubyte,to
将抛出异常。
在各种转换后打印元素可能有助于澄清在哪里发生的事情:
void main()
{
import std.algorithm, std.array, std.conv, std.stdio;
union hashU
{
ubyte[] hashA;
int[] hashN;
}
hashU a;
a.hashN = [1, 2, 3, 4, 5];
writeln( a.hashA ); /* union -> [1, 0, 0, 0, 2] (depends on endianess) */
writeln( cast(ubyte[])(a.hashN) );
/* cast -> [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0]
(depends on endianess) */
writeln( a.hashN.to!(ubyte[]) ); /* `to` -> [1, 2, 3, 4, 5] */
}
答案 1 :(得分:2)
据我所知,cast只是告诉编译器开始与你投射的内存块进行对话。
示例中的最后两个选项实际上将数字转换为新类型,因此执行一些实际工作。这就是他们最终成为相同价值观的原因。
前两个例子中的问题是int []的内存大于ubyte []。 (每个元素4个字节,每个元素1个字节)
我编辑了前两种方法:
/* Using an union, no actual data conversion */
md5.put( a.hashA );
auto hash = md5.finish();
writefln("Hash of: %s -> %s", a.hashA, hash);
// Hash of: [1, 0, 0, 0, 2] -> [253, 255, 63, 4, 193, 99, 182, 232, 28, 231, 57, 107, 18, 254, 75, 175]
// notice 5 bytes in first array
/* Using a cast... Doesn't match any of the other representations */
md5.put( cast(ubyte[])(a.hashN) );
hash = md5.finish();
writefln("Hash of: %s -> %s", cast(ubyte[])(a.hashN), hash);
// Hash of: [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0] -> [254, 5, 74, 210, 231, 185, 139, 238, 103, 63, 159, 242, 45, 80, 240, 12]
// notice 20 bytes (4 x 5 bytes) in first array
所以在第一个中,你正在读取ubyte []的字节长度。在第二个你将int []的长度转换为ubyte []。
编辑:问题尚不清楚。联合非常愚蠢,它只是将所有值存储在同一个内存中。当你去读取其中任何一个时,它只会读取该内存的X位,具体取决于你正在阅读的类型的长度。
因为你正在读取int [] THEN,所以它会读取所有20个字节并将它们转换为ubyte []。这当然不同于只读取ubyte []变量的5个字节。
我想我在那里有道理:))
答案 2 :(得分:0)
cast
是开发人员需要执行显式类型转换时使用的D运算符。