演员到底做了什么?
What does cast do exactly?
我在玩整数数组散列以及从一种表示到另一种表示的不同方式。我最终得到以下结果:
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 一样!或 union 技巧,但似乎并非如此。
据我所知,强制转换只是告诉编译器开始与您强制转换的内存块对话。
您示例中的最后两个选项实际上将数字转换为新类型,实际 工作也是如此。这就是为什么它们最终具有相同的值。
前两个示例中的问题是 int[] 在内存中比 ubyte[] 大。 (每个元素 4 个字节 vs 每个元素 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[] 然后转换它,它读取所有 20 个字节并将它们转换为 ubyte[]。这当然不同于仅仅读取 ubyte[] 变量的 5 个字节。
我觉得我说得有道理:)
我觉得 Colin Grogan 说得对,但是他的措辞有点混乱。
使用联合,数组被简单地重新解释,根本没有 calculation/computation 发生。 int[]
的指针和长度被重新解释为引用 ubyte
元素。之前:5 个整数,之后:5 个字节。
转换比这更聪明:它调整数组的长度,使其引用与以前相同的内存。之前:5 个整数,之后:20 ubytes (5*int.sizeof
/ubyte.sizeof
= 5*4/1 = 20).
union 和 cast 都将 int 的字节重新解释为 ubyte。也就是说,int 值 1 将产生 4 个 ubytes:0,0,0,1 或 1,0,0,0,具体取决于字节顺序。
to
变体将每个元素转换为新的元素类型。之前:5 个整数,之后:5 个字节,与整数具有相同的值。如果其中一个整数无法转换为 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] */
}
cast
是开发者需要进行显式类型转换时使用的D运算符
我在玩整数数组散列以及从一种表示到另一种表示的不同方式。我最终得到以下结果:
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 一样!或 union 技巧,但似乎并非如此。
据我所知,强制转换只是告诉编译器开始与您强制转换的内存块对话。
您示例中的最后两个选项实际上将数字转换为新类型,实际 工作也是如此。这就是为什么它们最终具有相同的值。
前两个示例中的问题是 int[] 在内存中比 ubyte[] 大。 (每个元素 4 个字节 vs 每个元素 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[] 然后转换它,它读取所有 20 个字节并将它们转换为 ubyte[]。这当然不同于仅仅读取 ubyte[] 变量的 5 个字节。
我觉得我说得有道理:)
我觉得 Colin Grogan 说得对,但是他的措辞有点混乱。
使用联合,数组被简单地重新解释,根本没有 calculation/computation 发生。 int[]
的指针和长度被重新解释为引用 ubyte
元素。之前:5 个整数,之后:5 个字节。
转换比这更聪明:它调整数组的长度,使其引用与以前相同的内存。之前:5 个整数,之后:20 ubytes (5*int.sizeof
/ubyte.sizeof
= 5*4/1 = 20).
union 和 cast 都将 int 的字节重新解释为 ubyte。也就是说,int 值 1 将产生 4 个 ubytes:0,0,0,1 或 1,0,0,0,具体取决于字节顺序。
to
变体将每个元素转换为新的元素类型。之前:5 个整数,之后:5 个字节,与整数具有相同的值。如果其中一个整数无法转换为 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] */
}
cast
是开发者需要进行显式类型转换时使用的D运算符