可以在 swift 中创建静态分配的数组吗?

2024-04-26

我想在 swift 中创建一个结构体,它有少量固定数量的值(比如 16 个浮点数)作为实例数据。要求该结构体不将这些值存储在堆上,以便结构体实例的地址就是实例变量的地址。还要求这些值可以通过下标在结构内部访问,就像数组一样。

在 C 语言中,你可以简单地定义这种事情:

struct Matrix4x4 {
    float elements[16];
    ...
} myMatrix;

有了这段代码,sizeof(Matrix4x4) == 64并且&myMatrix == &myMatrix.elements[0];简而言之,如果我类似地定义elements变量作为类型[Float],矩阵实例仅包含指向数组的指针,因为Array<Float>实例是存储在堆上的对象。

有没有一种方法可以快速获得实例变量的静态分配,而不放弃类似数组下标访问的便利性和效率?


目前,这在“纯 Swift”中是不可能的。有一个很长的讨论 在 swift-evolution 邮件列表中,起始地址为

  • [swift-evolution] 提案:连续变量(又名固定大小数组类型) https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160125/007984.html

它需要这样的功能,例如将矩阵结构传递给 C 函数。 据我所知,这个建议很受欢迎,但没有具体的计划 截至目前,它还没有被列入当前有效的 Swift 提案 https://github.com/apple/swift-evolution/tree/master/proposals.

C 数组

float elements[16];

作为包含 16 个组件的元组导入到 Swift 中:

public var elements: (Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float, Float)

目前,这似乎是定义具有给定内存布局的固定大小结构的唯一方法。 Apple 的 Joe Groff 撰文于[swift-user] 将 C 语义映射到 Swift https://lists.swift.org/pipermail/swift-users/Week-of-Mon-20160516/001968.html

Swift 结构具有未指定的布局。如果您依赖于特定的布局,您现在应该在 C 中定义该结构并将其导入到 Swift 中。

and 后来在那次讨论中 https://lists.swift.org/pipermail/swift-users/Week-of-Mon-20160516/001980.html:

您可以保留在 C 中定义的结构并将其导入到 Swift 中。 Swift 将尊重 C 的布局。

如果矩阵类型是在 C 头文件中定义的(为了简单起见,我使用 现在以 2x2 矩阵为例)

// matrix.h:
typedef struct Matrix2x2 {
    float elements[4];
} Matrix2x2;

然后将其导入到 Swift 中:

public struct Matrix2x2 {
    public var elements: (Float, Float, Float, Float)
    public init()
    public init(elements: (Float, Float, Float, Float))
}

如上所述,Swift 保留了 C 内存布局,因此矩阵及其 元素和第一个元素都具有相同的地址:

var mat = Matrix2x2(elements: (1, 2, 3, 4))
print(sizeofValue(mat)) // 16
withUnsafePointer(&mat) { print($0) }            // 0x00007fff5fbff808
withUnsafePointer(&mat.elements) { print($0) }   // 0x00007fff5fbff808
withUnsafePointer(&mat.elements.0) { print($0) } // 0x00007fff5fbff808

然而,元组是不可下标的,如果元组成员具有 不同种类。 swift-evolution 邮件列表上还有另一个讨论

  • [swift-evolution] 统一元组上的 CollectionType [分叉连续变量] https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160208/009682.html

将“统一元组”视为集合,这将允许下标。 不幸的是,这尚未实施。

有一些方法可以通过索引访问元组成员,例如使用Mirror() or withUnsafe(Mutable)Pointer().

这是一个可能的解决方案斯威夫特 3 (Xcode 8),这似乎运作良好 并且只涉及很少的开销。 “技巧”是定义 C 函数 返回指向元素存储的指针:

// matrix.h:

// Constant pointer to the matrix elements:
__attribute__((swift_name("Matrix2x2.pointerToElements(self:)")))
static inline const float * _Nonnull matrix2x2PointerToElements(const Matrix2x2 * _Nonnull mat)
{
    return mat->elements;
}

// Mutable pointer to the matrix elements:
__attribute__((swift_name("Matrix2x2.pointerToMutableElements(self:)")))
static inline float * _Nonnull pointerToMutableElements(Matrix2x2 * _Nonnull mat)
{
    return mat->elements;
}

我们需要两个变体来使正确的值语义发挥作用(下标设置器需要 变量、下标 getter 适用于常量或变量)。 “swift_name”属性使编译器将这些函数导入为成员 的职能Matrix2x2类型、比较

  • SE-0044 作为会员导入 https://github.com/apple/swift-evolution/blob/master/proposals/0044-import-as-member.md

现在我们可以在 Swift 中定义下标方法:

extension Matrix2x2 {
    public subscript(idx: Int) -> Float {
        get {
            precondition(idx >= 0 && idx < 4)
            return pointerToElements()[idx]
        }
        set(newValue) {
            precondition(idx >= 0 && idx < 4)
            pointerToMutableElements()[idx] = newValue
        }
    }
}

一切都按预期进行:

// A constant matrix:
let mat = Matrix2x2(elements: (1, 2, 3, 4))
print(mat[0], mat[1], mat[2], mat[3]) // 1.0 2.0 3.0 4.0

// A variable copy:
var mat2 = mat
mat2[0] = 30.0
print(mat2) // Matrix2x2(elements: (30.0, 2.0, 3.0, 4.0))

当然你也可以定义类似矩阵的下标方法

public subscript(row: Int, col: Int) -> Float

以类似的方式。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

可以在 swift 中创建静态分配的数组吗? 的相关文章

  • 如何用php将文件内容转换为字节数组

    我想用PHP将上传的文件保存 插入 到数据库中 数据库字段的类型是varbinary 最后 我想要获得 VarBinary 输出 的内容 就像在 C 中读取文件然后将其存储在字节数组中并将数组插入到 VarBinary 中一样 我与数据库的
  • 在某些情况下,直接访问字符串的后备数组是否合理?

    我正在致力于优化文本处理软件 其中经常使用以下类 class Sentence private final char textArray private final String textString public Sentence Str
  • 这里不允许使用数组初始值设定项[重复]

    这个问题在这里已经有答案了 我正在开发 Android 项目 但收到一个我无法理解的错误 这里不允许使用数组初始值设定项 我试图简化我的代码 结果归结为这一点 public class MainActivity extends Activi
  • 故事板中的 Xcode 6 UIVisualEffectView

    我正在 Xcode 6 中的对象库中查找 UIVisualEffectView 以在 Storyboard 中添加模糊效果 我知道如何以编程方式执行此操作 但我找不到在故事板中执行此操作的方法 这在当前的测试版中是否不可用 或者有没有一种不
  • Firebase 3.x - Facebook 登录

    InFirebase 2 5 1 我曾经这样做过 而且很有效 IBAction func facebookLoginDidTouch sender AnyObject let facebookLogin FBSDKLoginManager
  • 当 tableView 向下滑动时显示 UISearchController

    我通过 UISearchController 在我的测试应用程序中实现了搜索栏 当我启动应用程序时 我会在导航控制器下方看到搜索栏 但如何在应用程序启动时隐藏它并仅在下拉表格视图时显示它 并在拉出表格视图时再次隐藏 我在google或you
  • 是否可以仅使用密码进行身份验证,即使设备在 ios、swift 中具有 touch id 功能

    我要认证only使用PassCode甚至设备有Touch ID特征 我在用着 deviceOwnerAuthentication评估政策方法 当我使用这个时 如果用户已注册触摸 ID gt 始终要求提供触摸 ID 如果用户尚未注册 touc
  • HTML 表单:POST 对象数组

    提交班级名单 一次添加3名学生 每个学生都有最初 最后的年龄 问题 我们如何才能将所有学生放入数组中 students 0 gt Array first gt first name for 0 last gt last name for 0
  • AWS ios SDK - 弹性转码器作业的 http post 请求

    查看AWS弹性转码器 有几个问题 对于我的用例来说 首先使用转码器是否具有重要价值 我正在制作一个允许用户选择视频的 ios 应用程序 当他们这样做时 我会将其上传到 S3 存储桶 据我了解 我应该使用弹性转码器对这些视频进行转码 并将它们
  • 如何使用 Apple Map Kit 实现地址自动完成

    我想自动填写用户的地址 与 google api 在此链接中提供的地址相同 https developers google com maps documentation javascript places autocomplete hl e
  • 整数的十进制表示形式中的分隔数字

    例如 我想将用户输入作为整数输入 45697 并将前两位数字存储在数组 向量或其他内容中 例如 4 5 6 9 7 这样我就可以使用一些函数调用来检查前两个值 4 5 并对它们进行计算 问题 我不知道如何存储恢复前两个值 有没有简单的函数调
  • 如何在 Angular JS 中显示以字节数组形式接收的图像

    我有一个将返回图像的服务器端应用程序 这些是响应标头 Content Disposition attachment filename 8822a009 944e 43f4 999b d297198d302a 1 0 low res Cont
  • NSFileManager.defaultManager().fileExistsAtPath 返回 false 而不是 true

    这怎么可能 let exists NSFileManager defaultManager fileExistsAtPath path absoluteString print exists exists false This is pat
  • 从 MySQL 列创建 PHP 数组

    mysql fetch array会给我一个获取行的数组 从一列中所有行的值生成数组的最佳方法是什么 您可以循环遍历数组并创建一个新数组 如下所示 column array while row mysql fetch array info
  • C++:创建一个由用户输入大小的数组

    我想知道我们是否可以创建一个具有用户指定大小的数组 Ex int a cout lt lt Enter desired size of the array cin gt gt a int array a 上面的程序将不起作用 因为数组大小必
  • 在 C 中使用另一个结构中的二维结构数组的编码问题

    我正在使用一个二维结构数组 它是另一个结构的一部分 这不是我做过很多事的事情 所以我遇到了问题 该函数在接近末尾的 测试 for 循环后最终失败 它在出现段错误之前正确打印出一行 我的代码中将数据读入虚拟二维结构数组的部分工作得很好 所以它
  • 如何通过 CollectionView 中的流布局将单元格对齐到顶部

    在此代码中 我尝试更改 UICollectionView 的第一个单元格的大小以及具有相同大小的其他单元格的大小 但在第一行中 当我想要两个单元格出现时 只有一个单元格出现 func collectionView collectionVie
  • 如果数组重叠,则折叠多行数组

    我在 PostgreSQL 9 3 中有一个表 其中包含一个列 每行包含一个数组 我正在努力寻找崩溃的方法 共享相同元素的数组行 Examples 简单重叠 给定以下两行数组 1 2 3 5 3 6 9 结果将是一行包含 5 1 2 3 6
  • 在C中更改函数内的数组

    我正在学习 C 并且很困惑为什么在 main 中创建的数组不会在函数内部更改 我假设传递的数组是一个指针 并且更改指针应该更改数组 对吧 有人可以解释这种情况下发生了什么吗 谢谢你的帮助 int main int i length 10 i
  • iOS UITest:如何找到UITableViewCell的AccessoryView?

    你好我正在学习UITests now 我有个问题 如何检测accessoryView的点击tableViewCell 在UI测试中 下面是我的tableViewCell 我想要检测细节闭合配件视图水龙头 像这样 app tables cel

随机推荐

  • 实体框架无法使用复合键更新表中的数据 (Oracle)

    我们有一个具有三列复合键的 Oracle 表 这些列通过实体框架数据模型正确映射到 C 对象中 当我们从数据库中查询记录然后更新非键列时 我们总是收到一条错误消息 指出我们正在尝试更新主键 测试摘录如下 var connection new
  • 始终“具有离线访问权限”|谷歌 OAuth 2

    我正在尝试使用 Google OAuth2 api 获取用户的个人资料 用户身份验证后 在同意页面上 总是要求我 具有离线访问权限 浏览器中的 URL 如下所示 https accounts google com o oauth2 auth
  • Ember Data 未找到模型,但它显然存在

    我和其他许多人一样将我的 ember 应用程序升级到了最新版本 但升级后 我的应用程序仍然无法工作 我已经简化了很多 这归结为我的路线 我的路线是这样的 按照过渡指南中的建议 App BoxesRoute Ember Route exten
  • c++ pthread - 如何使地图访问线程安全?

    我有一个映射作为成员变量和多个访问该映射的线程 读写访问 现在我必须确保只有一个线程可以访问该地图 但我该如何点呢 最好的解决方案是什么 Boost 包含一些用于共享访问的很好的锁实现 看看文档 http www boost org doc
  • Google Play 游戏服务 - 未显示解锁成就弹出窗口

    当我解锁成就时 成就已解锁 弹出窗口不会弹出 但成就已解锁 正如我在成就列表中看到的那样 我已经尝试过了this https stackoverflow com a 26474719 2543285解决方案 但它不起作用 我在 MainAc
  • 将 JSON 数据从 php 传递到 html-data 属性,然后传递到 Javascript

    我正在创建一个插件 用户可以在其中添加自定义设置data HTML 中的属性 设置采用 JSON 格式 我在 Javascript 中使用这些设置 它有preview base and paths特性 preview and base有字符
  • Zurb Foundation:如何在调整大小到较小的屏幕时使按钮变小?

    在 Zurb Foundation 4 中 是否有一种方法可以在浏览器尺寸调整得较小或在较小的屏幕上时自动切换到较小的按钮样式 例如 当屏幕是标准桌面屏幕时 请执行以下操作 a href class primary button Butto
  • 计算具有特定子集大小的集合分区

    给定一组n元素 我需要找到该集合的所有分区k大小几乎相等的子集 例如 对于一个包含 7 个元素和 3 个子集的集合 我只需要其中有两个子集 每个子集包含 2 个元素 和一个子集包含 3 个元素的分区 我不想要一个包含 1 2 和 4 个元素
  • Visual Studio Javascript 断点未命中,为什么?

    可以为 javascript 代码块设置断点 如下图所示 我们如何使用它们 VS总是忽略 如果调试时将 Internet Explorer 设置为浏览器 理论上 Visual Studio 能够在客户端脚本设置的断点处停止 要使用该功能 您
  • Java Diffie-Hellman 密钥交换

    我正在尝试执行代码来执行 Diffie Hellman 密钥交换 我从网上的一个示例中获取了代码 现在忘记在哪里了 我必须导入 bouncycastle jar 我认为它在执行之前一直有效 my code package testproje
  • Golang - 如何在特定时间执行函数

    我需要在一天中的特定时间运行一个函数 例如 0010 0610 1210 1810 我目前的方法使用自动收报机for range time Tick 21600 time Second 我以这些时间间隔之一 例如 1210 手动启动该程序
  • C:如何将多位数分解为单独的变量?

    假设我在 C 中有一个多位整数 我想将它分解为一位数整数 123会变成1 2 and 3 我该如何做到这一点 特别是如果我不知道整数有多少位 int value 123 while value gt 0 int digit value 10
  • 如何在 openpyxl 进行更改时观察 Excel 文件更改

    我构建了一个 iOS 应用程序 它接受用户的输入 然后将其数据作为 csv 文件上传到 dropbox 现在 我想构建一个跨平台桌面应用程序 使用 openpyxl 和 Python dropbox api 来侦听这些 csv 上传 然后将
  • 如何在 Windows 中为高级网络适配器属性设置巨型数据包和接收/传输缓冲区?

    我正在尝试为网络适配器设置一些高级属性 例如巨型数据包 接收 发送缓冲区 我尝试使用 Win32 NetworkAdapter Win32 NetworkConnection Win32 NetworkAdapterConfiguratio
  • fab风格钻石如何使用?

    How to use diamond style for fab bottom app bar In the sketch files on the website https material io tools theme editor
  • 如何使用 powershell 以编程方式查找用户 HKEY_USERS 注册表项?

    我想知道如果您知道本地计算机上该用户的登录名 是否有办法在 HKEY USERS 中找到该用户的注册表项 我想以编程方式将内容添加到特定用户的注册表项 例如自动运行 但我只知道用户名 如何确定 HKEY USERS 中的哪些神秘用户实际上属
  • 如何在 Kaxaml 中引用不同的 DLL

    我想在 Kaxaml 中使用 DataGrid 如何引用工具包 dll Copy WPFToolkit dll to C Program Files Kaxaml 重新启动 Kaxaml 现在你可以使用这样的命名空间 xmlns dg cl
  • 三.js Raycaster intersectObjects

    我正在尝试修改这个例子 https github com timoxley threejs blob master examples webgl morphtargets md2 control html来自 Three js 通过鼠标点击
  • 错误:没有匹配的函数可供调用

    我在代码中收到 没有匹配的函数来调用错误 该代码在另一个类的构造函数中创建一个类的实例 代码如下 inline DiscriminatorContainer DiscriminatorContainer ushort id FebPtr f
  • 可以在 swift 中创建静态分配的数组吗?

    我想在 swift 中创建一个结构体 它有少量固定数量的值 比如 16 个浮点数 作为实例数据 要求该结构体不将这些值存储在堆上 以便结构体实例的地址就是实例变量的地址 还要求这些值可以通过下标在结构内部访问 就像数组一样 在 C 语言中