在Swift中,如何从一个整数中获取特定的位?

3

我将尝试将我的应用从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];

我无法找到有关如何从整数中选择特定位的任何参考资料... 有人知道吗?

3个回答

2
在Swift中可以使用|=运算符,其与C/C++中的用法相同。
问题在于C++代码中的load64()函数实际上将一个OCTETs数组作为参数,并使用下标访问该数组。Swift版本将UInt8作为参数,而在Swift、C或C++中,不能对整数执行下标操作。
据我所知,C++代码的目的是从提供的8个字节的数组中构建一个64位无符号整数。要在Swift中实现这一点,load64()需要接受一个字节数组作为参数,而不仅仅是单个字节。
顺便说一下,如果你有一个大型的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++包装器” - 非常好的建议!干杯。 - Tony Delroy
很抱歉,我的 Swift 代码出现了一点错误。实际上,该函数通过传递指针从一个更大的数组中加载整数值。下面是其他定义代码:#define readLane(x, y) load64((OCTET*)state+sizeof(tKeccakLane)*i(x, y))。state 是一个大小为 200 字节的数组。 - Wyllow Wulf
我会尝试使用包装器的想法或者找到另一种解决方法。 - Wyllow Wulf

0
我不知道 Swift 是否支持你尝试的 |=,但根据文档(谷歌上“swift按位或”的第一个匹配项),它应该支持:
let u = u | x[i]

他们的例子:

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

另外,如果您的C++代码在任何使用无符号字符的系统上运行,它将会陷入无限循环。


位或赋值运算符不是问题,问题在于 x[i]... 我正在尝试获取整数 x 的第 i 位。 - Wyllow Wulf
找到了几个选项... x & (1 << i) ? 1 : 0; (x >> i) & 1; - Wyllow Wulf
找到了几个选项... x & (1 << i) ? 1 : 0; (x >> i) & 1; (x & (0x01 << i)) ? 1 : 0; 我认为这会起作用...但有没有关于相反的想法,即分配给特定位? - Wyllow Wulf
@WilliamElliott:你可以通过与包含它的数字进行OR运算来分配到特定的位,而这个数字可以通过将1左移多少次来创建。 - Tony Delroy

0

如果需要更多的位数,通常会在 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)
{
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接