swift c语言数组

99ANYc3cd6
预计阅读时长 15 分钟
位置: 首页 C语言 正文

核心思想对比

特性 C 语言数组 Swift 数组
本质 一块连续的内存,数组名是一个指向其首元素的常量指针,它不存储自身的大小信息。 一个结构体Array 是一个泛型集合,它包含一个指向存储数据的连续内存缓冲区的指针,以及存储 count(元素数量)和 capacity(容量)等信息的属性。
类型安全 弱类型,编译器在编译时不会检查数组索引是否越界,也不会检查存入的类型是否匹配。 强类型Array<String> 只能存储字符串,编译器在编译时会进行严格的类型检查,防止类型不匹配的错误。
安全性 不安全,极易发生数组越界访问,导致未定义行为,如程序崩溃、数据损坏或安全漏洞。 非常安全,编译器会强制检查数组索引的有效范围,越界访问会直接导致编译错误。
动态性 静态大小,一旦定义,大小在编译时就已确定,无法改变,要改变大小,必须手动创建一个新数组并复制数据。 动态大小,可以随时添加或删除元素。Array 会自动管理底层的内存空间(扩容/缩容),开发者无需关心。
现代特性 ,没有泛型、闭包、高阶函数等现代特性。 丰富,支持泛型、可选类型、链式调用、高阶函数(map, filter, reduce 等),函数式编程风格。

C 语言数组详解

声明和初始化

C 语言数组的声明非常直接。

swift c语言数组
(图片来源网络,侵删)
// 1. 声明并初始化,大小由编译器推断
int numbers[] = {1, 2, 3, 4, 5}; 
// sizeof(numbers) / sizeof(numbers[0]) 会得到 5
// 2. 声明时指定大小
int scores[10]; // 创建一个包含10个int元素的数组,初始值为垃圾值
// 3. 显式初始化所有元素为0
int zeros[100] = {0}; 
// 4. 部分初始化,其余元素自动为0
int partial[5] = {1, 2}; // partial 是 {1, 2, 0, 0, 0}

访问元素

通过索引访问,从 0 开始。

int first_element = numbers[0]; // 1
numbers[2] = 99; // 修改第三个元素为99

关键特性与风险

  • 内存是连续的numbersnumbers + 1 在内存中是相邻的。
  • 越界是“沉默的杀手”
      int arr[5] = {0};
      arr[10] = 100; // 编译器不会报错!这会破坏内存中的其他数据,可能导致程序崩溃。
  • 没有内置的长度信息:你必须自己计算或传递数组的长度。
      void print_array(int arr[], int size) {
          for (int i = 0; i < size; i++) {
              printf("%d ", arr[i]);
          }
      }
  • 动态数组需要手动管理:如果你想实现一个可以增长的数组,你需要:
    1. 使用 malloccalloc 分配内存。
    2. 当空间不够时,使用 realloc 分配一个更大的新内存块。
    3. 手动复制旧数据到新内存。
    4. 释放旧内存 free。 这是一个繁琐且容易出错的过程。

Swift 数组详解

声明和初始化

Swift 的 Array 是一个结构体,它是一个值类型。

// 1. 类型推断:编译器自动推断为 [Int]
var numbers = [1, 2, 3, 4, 5]
// 2. 显式声明类型
var scores: [Int] = [10, 20, 30]
// 3. 创建一个指定大小并填充默认值的数组
var zeros = Array(repeating: 0, count: 100)
// 4. 创建一个空数组
var emptyArray: [String] = []
var anotherEmptyArray = [String]()

访问和修改元素

通过索引访问,但 Swift 的索引是安全的。

var firstElement = numbers[0] // 1
numbers[2] = 99 // 修改第三个元素
// --- 安全特性演示 ---
// numbers[10] = 100 // 这行代码会直接导致编译错误!
// Error: Index out of range

关键特性与优势

  • 类型安全

    swift c语言数组
    (图片来源网络,侵删)
      var names = ["Alice", "Bob"]
      // names.append(123) // 编译错误!不能将 Int 添加到 [String] 数组中。
  • 动态大小

      var fruits = ["Apple"]
      fruits.append("Banana") // 动态添加
      fruits += ["Cherry", "Date"] // 动态添加多个
      fruits.remove(at: 0) // 动态删除
      print(fruits.count) // 输出 3
  • 内置属性和方法

      print(numbers.count) // 5
      print(numbers.isEmpty) // false
      numbers.removeAll() // 清空数组
  • 现代化的操作(函数式编程)

      let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
      // map: 转换
      let doubled = numbers.map { $0 * 2 } // [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
      // filter: 过滤
      let evens = numbers.filter { $0 % 2 == 0 } // [2, 4, 6, 8, 10]
      // reduce: 归纳
      let sum = numbers.reduce(0, +) // 55
      // forEach: 遍历
      numbers.forEach { print($0) }
  • 值语义Array 是一个值类型,当你把它赋值给一个新变量或传递给函数时,会创建一个副本

      var originalArray = [1, 2, 3]
      var copiedArray = originalArray
      copiedArray.append(4)
      print(originalArray) // [1, 2, 3] (原数组不变)
      print(copiedArray)   // [1, 2, 3, 4] (新数组有修改)

    注意:虽然数组本身是值类型,但如果数组存储的是引用类型(如自定义的类对象),那么复制的只是对象的引用,而不是对象本身。


何时使用哪种数组?

使用 C 语言数组的情况:

  1. 性能要求极致:在操作系统内核、嵌入式系统、游戏引擎或高性能计算中,需要手动控制内存布局,避免任何抽象层的开销。
  2. 与 C API 交互:调用 Objective-C 或纯 C 语言的库时,它们通常期望接收 C 风格的数组。
  3. 资源受限环境:在内存极其有限的设备上,C 数组最小的内存开销(只有数据本身)是优势。
  4. 需要底层内存操作:直接操作像素数据、网络数据包等。

使用 Swift 数组的情况:

  1. 绝大多数应用开发:无论是 iOS、macOS、服务器端还是其他 Swift 项目,都应该优先使用 Swift 的 Array,它更安全、更易用、功能更强大。
  2. 代码可维护性和安全性:Swift 数组的类型安全和越界保护能从源头上避免大量常见的运行时错误。
  3. 利用现代 Swift 生态:当你需要使用 SwiftUI、Combine、async/await 等现代框架时,它们与 Swift 的集合类型无缝集成。
  4. 团队开发:强类型和高层次抽象能帮助团队成员更好地理解代码,减少协作中的摩擦。
方面 C 数组 Swift 数组
哲学 手动、底层、高效 自动、高层、安全
学习曲线 简单,但陷阱多 稍复杂,但设计优雅
开发效率 低(需手动管理内存和边界) 高(自动管理,编译器辅助)
安全性 低(易出内存错误) 高(编译器保证类型和边界安全)
适用场景 系统编程、性能关键部分、与C库交互 通用应用开发、现代Swift项目

除非你有非常特殊的需求(如直接与C代码交互或追求极致的底层性能),否则在 Swift 中应该始终选择使用 Swift 的 Array,它代表了现代编程语言设计的最佳实践,能让你更专注于业务逻辑,而不是底层的内存管理细节。

-- 展开阅读全文 --
头像
c语言 开源 line
« 上一篇 04-06
织梦cms 后台地址
下一篇 » 04-06

相关文章

取消
微信二维码
支付宝二维码

目录[+]