如何从 Swift 中的整数中获取特定位?

How do I get a specific bit from an Integer in Swift?

正在尝试将我的应用程序从 C++ 转换为 Swift

C++:

static QWORD load64(const OCTET *x)
{
char i;
QWORD u=0;
    for(i=7; i>=0; --i) {
        u <<= 8;
        u |= x[i];
    }
    return u;
}

Swift:

func load64(x: UInt8) -> UInt64 {
    var u: UInt64 = 0;
    for var i=7; i>=0; --i {
        u <<= 8;
        u |= x[i];
    }
    return u;
}

但是这条线在 Swift 中不起作用:

u |= x[i];

而且我似乎找不到任何关于从整数中选择特定位的参考...有人知道怎么做吗?

我不知道 swift 是否像您尝试的那样支持 |=,但根据 the docs("swift bitwise-or" 在 [=21= 上的第一次匹配]), 它应该支持:

let u = u | x[i]

他们的例子:

let someBits: UInt8 = 0b10110010
let moreBits: UInt8 = 0b01011110
let combinedbits = someBits | moreBits // equals 11111110

另外,您的 C++ 代码将在任何具有无符号字符的系统上陷入无限循环。

可以在 Swift 中使用 |= 运算符,其作用与 C/C++ 中的相同。

问题在于 C++ 代码中的 load64() 本质上是将一个 OCTET 数组作为参数并使用下标访问该数组。 Swift 版本接受一个 UInt8 作为参数,你不能在 Swift 中下标一个整数,就像你不能在 C 或 C++ 中那样做。

据我所知,C++ 代码的要点是从作为参数传入的数组中提供的 8 字节数组构建一个 64 位无符号整数。为了让它在 Swift 中工作,load64() 需要将一个字节数组作为参数,而不仅仅是一个字节。

顺便说一句,如果您想在 Swift 中使用 C++ 或 C 的大型代码库,则不必在 Swift 中重新编写它。您可以编写一个具有简化接口的 C/C++ 包装器并从 Swift 调用它。我有一个关于如何在此处执行此操作的基本概念验证教程:http://www.swiftprogrammer.info/swift_call_cpp.html

顺便说一句,这是 load64() 的 Swift 版本,对我有用:

func load64(x: [UInt8]) -> UInt64 {
    var u: UInt64 = 0;
    for var i=7; i>=0; --i {
        u <<= 8;
        u |= UInt64(x[i]);
    }
    return u;
} 

如果位数更多,您通常会在 C/C++ 中使用 struct:

struct MyBitsAndPieces
{
    unsigned char bit0 :1;
    unsigned char bit1 :1;
    ...
};

然后您可以访问各个位:

struct MyBitsAndPieces baps = 2;
if (baps.bit1 == 1)
{
}

类似的事情可以在Swift中完成:

struct MyBitsAndPieces: OptionSet
{
    let rawValue: UInt8

    static let bit0 = MyBitsAndPieces(rawValue: 1 << 0)
    static let bit1 = MyBitsAndPieces(rawValue: 1 << 1)
    ...
}

您可以使用以下方法初始化并检查一下:

let baps = MyBitsAndPieces(rawValue: 2)
if baps.contains(.bit1)
{
}