移植C字节序&指向斯威夫特的黑魔法

时间:2015-06-20 18:39:49

标签: c swift pointers endianness

我正在尝试翻译此代码段:

ntohs(*(UInt16*)VALUE) / 4.0
从C到斯威夫特,其他一些看起来相似的东西。 问题是,我对Swift知之甚少,而我无法理解这段代码的作用......以下是我所知道的:

  • ntohs swap endianness to host endianness
  • VALUEchar[32]
  • 我刚刚发现Swift:(UInt(data.0) << 6) + (UInt(data.1) >> 2)做同样的事情。可以解释一下吗?
  • 我愿意回复斯威夫特UintUInt64

谢谢!

3 个答案:

答案 0 :(得分:7)

  1. VALUE是指向32个字节(char[32])的指针。
  2. 指针被强制转换为UInt16指针。这意味着VALUE的前两个字节被解释为UInt16(2个字节)。
  3. *将取消引用指针。我们得到VALUE的两个字节作为16位数。但是它有net endianness(净字节顺序),所以我们不能对它进行整数运算。
  4. 我们现在将endianness交换为host,我们得到一个正常的整数。
  5. 我们将整数除以4.0
  6. 要在Swift中执行相同操作,我们只需将字节值组合为整数。

    let host = (UInt(data.0) << 8) | UInt(data.1)
    

    请注意,要除以4.0,您必须将整数转换为Float

答案 1 :(得分:2)

你引用的C在技术上是不正确的,虽然它将按照大多数生产C编译器的预期编译.¹实现相同效果的更好方法,也应该更容易转换为Swift,

unsigned int val = ((((unsigned int)VALUE[0]) << 8) |  // ² ³
                    (((unsigned int)VALUE[1]) << 0));  // ⁴

double scaledval = ((double)val) / 4.0;                // ⁵

第一个语句读取VALUE的前两个字节,将它们解释为网络字节顺序中的16位无符号数,并将它们转换为主机字节顺序(无论这些字节顺序是否不同)。第二个语句将数字转换为double并对其进行缩放。

¹具体来说,*(UInt16*)VALUE会引发未定义的行为,因为它违反了基于类型的别名规则,即非对称:带有字符类型的指针可用于访问任何类型的对象,但是具有任何其他类型的指针可能用于访问具有(array-of-)字符类型的对象。

²在C中,为了使后续的移位和or-ing以无符号类型发生,这里需要转换为unsigned int。如果您转换为uint16_t,这似乎更合适,那么“通常的算术转换”会在执行左移之前将其转换为已签名的int。这会在int仅为16位宽的系统上引发未定义的行为(不允许您转换到符号位)。对于具有小范围的类型,Swift几乎肯定具有完全不同的算法规则;你可能需要在轮班之前投出某事,但我不能告诉你什么。

³我对这个表达式进行了过度括号化,这样即使你对C语言并不十分熟悉,操作的顺序也会很清楚。

⁴左移零位无效;它仅包含在并行结构中。

C在C中不需要在除法运算之前显式转换为double,但它在Swift中,所以我在这里写了这个。

答案 2 :(得分:-2)

看起来代码采用单字节值[0]。然后取消引用,这应该从低内存地址1到127(可能是255)检索一个数字。 那么什么数字除以4。

我真的不敢相信我的解释是正确的,不能检查我没有笔记本电脑。我真的认为你的代码中可能存在拼写错误,因为它不是一件好事。便携式,可重复使用

我必须强调字符串不会转换为数字。然后使用