C# 指针的黑魔法

C# 指针的黑魔法,c#,c,C#,C,我有一个uint8\t state[16][8]具有以下值: 86 a9 d2 4e 23 f4 b1 3 b7 2b 8c 69 d1 f1 bb b5 11 7e c3 1 76 4直流测向 6b f0 4f 3d a9 5c 2 68 8 f4 ee 6f 1b e6 90 3b 32 4c 4e 27 99 c b2 4e f6 9d d5 8d为84 81 3e e0 a5 2f 66 31 23 98 75 e4 52比照77 42 ad 3 61 406B 32612 01 0 0

我有一个
uint8\t state[16][8]
具有以下值:

86 a9 d2 4e 23 f4 b1 3
b7 2b 8c 69 d1 f1 bb b5
11 7e c3 1 76 4直流测向
6b f0 4f 3d a9 5c 2 68
8 f4 ee 6f 1b e6 90 3b
32 4c 4e 27 99 c b2 4e
f6 9d d5 8d为84 81 3e
e0 a5 2f 66 31 23 98 75
e4 52比照77 42 ad 3 61
406B 32612 01 0
0 0 fd 60 56 1d c 61
4f cb 22 0 ff ff ff
2 0 1 0 e8 98 8 61
fd 6e 22 61 94 60 cf 77
ac a2 d0 77 20 64 2e 61
0 0 10 cc 22 0
当我这样做的时候

uint64_t* s = (uint64_t*)state;
然后打印
uint64t*s
,我得到这样的
uint64\u t
值:

4ed2a986
698c2bb7
1c37e11
3d4ff06b
6feef408
274e4c32
8dd59df6
662fa5e0
有人能给我解释一下转换的“黑魔法”吗

更具体地说,我需要将此转换从C函数移植到C#方法


感谢

在分析此类情况时,将数字缓冲为零是很有帮助的,因此您的
状态实际上变成了

86 a9 d2 4e 23 f4 b1 03
b7 2b 8c 69 d1 f1 bb b5
11 7e c3 01 76 04 dc df
6b f0 4f 3d a9 5c 02 68
08 f4 ee 6f 1b e6 90 3b
32 4c 4e 27 99 0c b2 4e
f6 9d d5 8d be 84 81 3e
e0 a5 2f 66 31 23 98 75
e4 52 cf 77 42 ad 03 61
40 6b 32 61 02 00 01 00
00 00 fd 60 56 1d 0c 61
4f cb 22 00 ff ff ff ff
02 00 01 00 e8 98 08 61
fd 6e 22 61 94 60 cf 77
ac a2 d0 77 20 64 2e 61
00 00 00 00 10 cc 22 00
从这里开始,
s
中的每个结果显然都是每行的前半部分,并且(正如chris在评论中提到的)颠倒了

按照赵的评论,结果似乎不是64位长,导致了这个“上半部分”问题;这些结果似乎是转换为
uint32\t
而不是64位的结果,因为它们每个只有32位。

在机器(如x86和x64机器)上,整数字节按从最低有效到最高有效的顺序排列。例如,64位整数

0x1234567890ABCDEF0
在内存中按如下方式存储:

F0 DE BC 9A 78 56 34 12
因此,在一台小型endian机器上,您提供的C代码实际上生成以下数字:

86 a9 d2 4e 23 f4 b1 03 = 0x03b1f4234ed2a986 =   266262285475031430
b7 2b 8c 69 d1 f1 bb b5 = 0xb5bbf1d1698c2bb7 = 13095326223231101879
11 7e c3 01 76 04 dc df = 0xdfdc047601c37e11 = 16130772870216515089
6b f0 4f 3d a9 5c 02 68 = 0x68025ca93d4ff06b =  7494654611845804139
08 f4 ee 6f 1b e6 90 3b = 0x3b90e61b6feef408 =  4292183450400519176
32 4c 4e 27 99 0c b2 4e = 0x4eb20c99274e4c32 =  5670608732741848114
f6 9d d5 8d be 84 81 3e = 0x3e8184be8dd59df6 =  4504027056305446390
e0 a5 2f 66 31 23 98 75 = 0x75982331662fa5e0 =  8473561393972356576
e4 52 cf 77 42 ad 03 61 = 0x6103ad4277cf52e4 =  6990621547598664420
40 6b 32 61 02 00 01 00 = 0x0001000261326b40 =      281485197339456
00 00 fd 60 56 1d 0c 61 = 0x610c1d5660fd0000 =  6992996578231123968
4f cb 22 00 ff ff ff ff = 0xffffffff0022cb4f = 18446744069416864591
02 00 01 00 e8 98 08 61 = 0x610898e800010002 =  6992006543692595202
fd 6e 22 61 94 60 cf 77 = 0x77cf609461226efd =  8633225201093603069
ac a2 d0 77 20 64 2e 61 = 0x612e642077d0a2ac =  7002644561219592876
00 00 00 00 10 cc 22 00 = 0x0022cc1000000000 =     9794518299705344
(由于print语句中存在错误,因此获得了不同的值。)

在同一台机器上,以下代码产生相同的编号:

ulong value = BitConverter.ToUInt64(data, 0);

无论是提供的C代码还是等效的C代码都不应用于从一台机器发送到另一台机器的数据。

@FrançoisAndrieux您是对的,可能应该提到,这些不是
uint64\u t
s。顺便说一句,您可能违反了严格的别名规则,因此有UB。@Jarod42,我认为OP没有编写C代码,我想他们不明白你想和他们交流什么。我在回答中没有提到可能的边界问题,因为OP试图编写匹配的C#代码,而不是修复其他人的C代码(即使它不可移植也能工作)。Re“从那里开始,你在s中的每个结果显然是每行的前半部分,并且(正如chris在评论中提到的)结尾颠倒。”,
s
包含由整行组成的
0x03b1f4234ed2a986
。@ikegami,我只看到
4ed2a986
作为问题的第一行,这是我获取数据的地方。我没有运行代码,因为讨论的那部分达到了“坏问题数据”状态。第一行是
86 a9 d2 4e 23 f4 b1 3
*s
包含
0x03b1f4234ed2a986
(而不是
0x4ed2a986
)。您可能需要在打印语句中使用%llx。