1

给定这个字段:

char lookup_ext[8192] = {0}; // Gets filled later

而这个声明:

unsigned short *slt = (unsigned short*) lookup_ext;

幕后会发生什么?

lookup_ext[1669] 返回 67 = 0100 0011 (C),lookup_ext[1670] 返回 78 = 0100 1110 (N),lookup_ext[1671] 返回 68 = 0100 0100 (D);然而 slt[1670] 返回 18273 = 0100 0111 0110 0001。

我正在尝试将它移植到 C#,所以除了一个简单的方法之外,我还想知道这里到底发生了什么。自从我经常使用 C++ 以来已经有一段时间了。

谢谢!

4

4 回答 4

6

您显示的语句不会将 char 转换为 unsigned short ,而是将指向char 的指针转换为指向 unsigned short 的指针。这意味着指向数据的通常算术转换不会发生,并且当通过slt变量访问时,底层的 char 数据将被解释为无符号短路。

请注意,sizeof(unsigned short)不太可能是一个,因此slt[1670]不一定对应于lookup_ext[1670]. 更有可能 - 如果,比如说,sizeof(unsigned short)是两个 - 对应于lookup_ext[3340]lookup_ext[3341]

你知道为什么原始代码使用这个别名吗?如果没有必要,可能值得尝试使 C++ 代码更清晰,并在移植之前验证行为是否未更改。

于 2008-12-31T09:48:22.280 回答
2

如果我理解正确,类型转换会将大小为 8192 的 char 数组转换为大小为该大小一半的短 int 数组,即 4096。

所以我不明白你在你的问题中比较什么。slt[1670] 应该对应lookup_ext[1670*2] 和lookup_ext[1670*2+1]。

于 2008-12-31T09:47:49.690 回答
1

嗯,这个说法

char lookup_ext[8192] = {0}; // Gets filled later

根据定义发生的位置,在本地或非本地创建一个数组。像这样初始化它,使用聚合初始化器会将其所有元素初始化为零(第一个显式地初始化,其余的隐式地初始化)。因此我想知道为什么你的程序输出非零值。除非填充发生在读取之前,否则这是有道理的。

unsigned short *slt = (unsigned short*) lookup_ext;

当您从该指针的目标读取时,这会将构成数组的字节解释为无符号短对象。严格来说,以上是未定义的行为,因为您无法确定数组是否适合对齐,并且您会从未指向原始指向类型的类型的指针(unsigned char <-> unsigned short)中读取。在 C++ 中,从其他 pod 中读取值的唯一可移植方法(普通的旧数据。这也是 C 中可能的所有结构和简单类型(例如 short),广义上讲)是使用这样的库函数:memcpymemmove

因此,如果您阅读*slt上面的内容,您将解释sizeof(*slt)数组的第一个字节,并尝试将其读取为 unsigned short(称为type pun)。

于 2008-12-31T10:00:36.357 回答
0

当您执行“unsigned short slt = (unsigned short )lookup_ext;”时,没有。从lookup_ext给定的位置拾取相当于(unsigned short)大小的字节,并存储在slt指向的位置。由于 unsigned short 将是 2 个字节,lookup_ext 的前两个字节将存储在 slt 给定的位置。

于 2008-12-31T09:49:42.103 回答