如何从 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)
{
}
正在尝试将我的应用程序从 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)
{
}