四、函数

//1.函数的定义,形参默认是let 也只能是let,let省略了
func pi() -> Double {
    return 3.14
}
pi()

func sum0(v1: Int, v2: Int) -> Int {
    return v1 + v2
}
print(sum0(v1:1,v2:2))

//3个无返回值等价 Void就是空元组
public typealias Void = ()
func sayHello0() -> Void {
    print("Hello0")
}
func sayHello1() -> () {
    print("Hello1")
}
func sayHello2() {
    print("Hello2")
}
sayHello0()
sayHello1()
sayHello2()

//隐式返回:如果函数体是一个单一的表达式,那么函数会隐式返回这个表达式
func sum1(v1: Int, v2: Int) -> Int {
    v1 + v2
}
print(sum1(v1: 10, v2: 20))

//返回元组:实现多返回值
func calculate(v1: Int, v2: Int) -> (sum2: Int, difference: Int, average: Int) {
    let sum2 = v1 + v2
    return (sum2, v1 - v2, sum2 >> 1) //结合10进制理解这个移位
}
let result = calculate(v1: 20, v2: 10)
result.sum2
result.difference
result.average

//函数的文档注释

///  求和【概述】
///
/// 将2个整数相加【更详细的描述】
///
/// - Parameter v1:第1个参数
/// - Parameter v2:第2个参数
/// - Returns:2个整数的和
///
/// - Note:传入2个整数即可【批注】
///
func sum3(v1: Int, v2: Int) -> Int {
    v1 + v2
}

sum3(v1: 1, v2: 2)

//参数标签
//可以修改参数标签 time在内用 at在外用
func goToWork(at time: String) {
    print("this time is \(time)")
}
goToWork(at: "08:00") //为什么这么设计?更像个句子好理解

func goToWork(time: String) {
    print("this time is \(time)")
}
goToWork(time: "08:00")//this time is 08:00

//可以使用下划线省略_ 省略参数标签,尽量少用,多用上边,易读
func sum4(_ v1: Int, _ v2: Int) -> Int {
    v1 + v2
}
sum4(10,20)

//默认参数值
//参数可以有默认值
func check(name: String = "nobbody", age: Int, job: String = "none") {
    print("name = \(name), age = \(age), job = \(job)")
}
check(name: "Jack", age: 20, job: "Doctor")//name = Jack, age = 20, job = Doctor
check(name: "Rose", age: 18)//name = Rose, age = 18, job = none
check(age: 10, job: "aaa")//name = nobbody, age = 10, job = aaa
check(age: 15)//name = nobbody, age = 15, job = none
//C++的默认参数值有个限制:必须从右往左设置。由于swift拥有参数标签,因此并没有此类限制,但是在省略参数标签时特别注意,避免出错
//这里的middle参数不可省略参数标签
func test(_ first: Int = 10, middle: Int, _ last: Int = 30) {}
test(middle:20)

//可变参数,一个函数最多只能有一个可变参数
func sum5(_ numbers: Int...) -> Int {
    var total = 0
    for number in numbers {
        total += number
    }
    return total
}
sum5(10, 20, 30, 40)//100

//Swift自带的print函数
print("1","2","3",separator:"",terminator:"")
print(20)//12320

//紧跟在可变参数后面的参数不能省略参数标签 参数 string 不能省略标签,为什么?string: String如果是string: Int就分辨不清了怎么传值了
func test0(_ numbers: Int..., string: String, _ other: String) {}
test0(10, 20, 30, string: "Jack", "Rose")

//输入输出参数:可以用inout定义一个输入输出参数:可以在函数内部修改外部实参的值
//可变参数不能标记为inout,
//inout 参数不能有默认值,
//inout参数只能传入被多次赋值的,变量,数组元素
var numbers0 = [10, 20, 30]
numbers0[0] = 20
numbers0[0] = 30
func test1(_ num: inout Int) {
    
}
test1(&numbers0[0])

//inout参数的本质设计地址传递(引用传递)//汇编看出来的 lea是地址传递
func swapValues0(_ v1: inout Int, _ v2: inout Int) {
    let tmp = v1
    v1 = v2
    v2 = tmp
}
var num1 = 10
var num2 = 20
swapValues0(&num1, &num2)

func swapValues1(_ v1: inout Int, _ v2: inout Int) {
    (v1, v2) = (v2, v1)
}

swap(&num1, &num2)

//修改外部变量的值
var number0 = 10
func add(_ num: inout Int) {
    num = 20
}
add(&number0)//20

//函数重载
//函数名相同,参数个数不同||参数类型不同||参数标签不同
func sum6(v1: Int, v2: Int) -> Int {
    v1 + v2
}
//参数个数不同
func sum6(v1: Int, v2: Int, v3: Int) -> Int {
    v1 + v2 + v3;
}
//参数类型不同
func sum6(v1: Int, v2: Double) -> Double {
    Double(v1) + v2
}
//参数标签不同
func sum6(_ v1: Int, _ v2: Int) -> Int {
    v1 + v2
}
//参数标签不同
func sum6(a: Int, b: Int) -> Int {
    a + b
}
sum6(v1: 10, v2: 20)
sum6(v1: 10, v2: 20, v3: 30)
sum6(v1: 10, v2:20.0)
sum6(10, 20)
sum6(a: 10, b: 20)
//函数重载注意点
//1函数返回值类型与函数重载无关
func sum7(v1: Int, v2: Int) -> Int { v1 + v2 }
func sum7(v1: Int, v2: Int) {}
//sum7(v1: 10, v2: 20)//报错

//2默认参数值和函数重载一起使用产生二义性时,编译器并不会报错(在C++中会报错)
func sum8(v1: Int, v2: Int) -> Int {
    v1 + v2
}
func sum8(v1: Int, v2: Int, v3: Int = 10) -> Int {
    v1 + v2 + v3
}
sum8(v1: 10, v2: 20)//会调用sum8(v1: Int, v2: Int)
//3可变参数、省略参数标签、函数重载三者一起使用产生二义性时,编译器有可能会报错
//func sum9(v1: Int, v2: Int) -> Int {
//    v1 + v2
//}
//func sum9(_ v1: Int, _ v2: Int) -> Int {
//    v1 + v2
//}
//func sum9 (_ numbers: Int...) -> Int {
//    var total = 0
//    for number in numbers {
//        total += number
//    }
//    return total
//}
//sum9(10, 20)

/*
 内联函数
 如果开启了编译器优化,release模式默认会开启优化,编译器会自动将某些函数变成内联函数,将函数调用展开成函数体. Build Setting -> optimization
 哪些函数不会被自动内联?
 1.函数体比较长 2.包含递归调用 3.包含动态派发

 
 */

//理解函数内联
func test2() {
    print()
}

test2()//函数内联后这句实际是print(),少了函数调用压栈出栈等操作直接把函数体放在了这里
//理解动态派发
class Person {
    func test3() {
    }
}
class Student: Person {
    override func test3() {
    }
}
class Teacher: Person {
    override func test3() {
    }
}

var p : Person = Student()
p = Teacher()
p.test3() //编译器无法决定调用哪个函数

//在release模式下,编译器已经开启优化,会自动决定哪些函数需要内联,因此没必要使用@inline
//永远不会被内联,即使开启了编译器优化
@inline(never) func test4() {
    print("test4")
}
//开启编译器优化,即使代码很长,也会被内联(递归调用函数、动态派发的函数除外)
@inline(__always) func test5() {
print("test5")

//函数类型
//每一个函数都是有类型的,函数类型由形式参数类型、返回值类型组成
func test4() {}// () -> Void 或者 () -> ()
func sum10(a: Int, b: Int) -> Int { // (Int, Int) -> Int
    a + b
}
//定义变量
var fn: (Int, Int) -> Int = sum10 //调用时不需要参数标签

//函数类型作为函数参数
func sum11(v1: Int, v2: Int) -> Int {
    v1 + v2
}
func difference0(v1: Int, v2: Int) -> Int {
    v1 - v2
}
func printResult(_ mathFn: (Int, Int) -> Int, _ a: Int, _ b: Int) {
    print("Result: \(mathFn(a,b))")
}
printResult(sum11, 5, 2) //Result: 7
printResult(difference0, 5, 2) //Result: 3

//高阶函数:返回值是函数类型的函数
func next(_ input: Int) -> Int {
    input + 1
}
func previous(_ input: Int) -> Int {
    input - 1
}
func forward(_ forward: Bool) -> (Int) -> Int {//(Int) -> Int返回值类型
    forward ? next : previous
}
forward(true)(3) //4
forward(false)(3) //2

//typealias 用来给类型起别名
typealias Byte = Int8
//元组
typealias Date = (year: Int, moth: Int, day: Int)
func test5(_ date: Date) {
    print(date.0)
    print(date.year)
}
test5((2011, 9, 10))

typealias IntFn = (Int, Int) -> Int
func difference1(v1: Int, v2: Int) -> Int {
    v1 - v2
}
let fn: IntFn = difference1
fn(20, 10)
func setFn(_ fn: IntFn) {}
setFn(difference1)
func getFn() -> IntFn {difference1}

//函数嵌套:将函数定义在函数内部,不想让外部调用到
func forward0(_ forward0: Bool) -> (Int) -> Int {
    func next(_ input: Int) -> Int {
        input + 1
    }
    func previous(_ input: Int) -> Int {
        input - 1
    }
    return forward0 ? next : previous
}
forward0(true)(3) //4
forward0(false)(3) //2

//8.枚举变量的内存布局
enum TestEnum : Int {
    case test1, test2, test3
}
var t = TestEnum.test1
print(Mems.ptr(ofVal: &t))
t = .test2
t = .test3
//枚举变量的原始值没有存储在枚举变量里,不用管它存储在哪里,完全可以写代码返回rawValue的值

enum TestEnum0 {
    case test1(Int, Int, Int)
    case test2(Int, Int)
    case test3(Int)
    case test4(Bool)
    case test5
}
//01 00 00 00 00 00 00 00
//02 00 00 00 00 00 00 00
//03 00 00 00 00 00 00 00
//00
//00 00 00 00 00 00 00
var e = TestEnum0.test1(1, 2, 3)
print(Mems.memStr(ofVal: &e,alignment: .one))
//04 00 00 00 00 00 00 00
//05 00 00 00 00 00 00 00
//00 00 00 00 00 00 00 00
//01
//00 00 00 00 00 00 00
e = TestEnum0.test2(4, 5)
print(Mems.memStr(ofVal: &e))
//06 00 00 00 00 00 00 00
//00 00 00 00 00 00 00 00
//00 00 00 00 00 00 00 00
//02
//00 00 00 00 00 00 00
e = TestEnum0.test3(6)
print(Mems.memStr(ofVal: &e))
//01 00 00 00 00 00 00 00
//00 00 00 00 00 00 00 00
//00 00 00 00 00 00 00 00
//03
//00 00 00 00 00 00 00
e = TestEnum0.test4(true)
print(Mems.memStr(ofVal: &e))
//00 00 00 00 00 00 00 00
//00 00 00 00 00 00 00 00
//00 00 00 00 00 00 00 00
//04
//00 00 00 00 00 00 00
e = TestEnum0.test5
print(Mems.memStr(ofVal: &e))
//枚举变量的成员值和关联值存储在枚举变量里边,1个字节存储成员值,N个字节存储关联值,N取占用内存最大的case关联值,任何一个的case的关联值都共用这个N个字节,如果只有1个成员值就不需要字节存储成员值了

enum TestEnum1 {
    case test
}
print((MemoryLayout<TestEnum1>.stride)) //1
print(MemoryLayout<TestEnum1>.size)//0
print((MemoryLayout<TestEnum1>.alignment))//1

enum TestEnum2 {
    case test(Int)
}
var t2 = TestEnum2.test(10)
print((MemoryLayout<TestEnum2>.stride))//8
print(MemoryLayout<TestEnum2>.size)//8
print((MemoryLayout<TestEnum2>.alignment))//8

enum TestEnum3 {
    case test(Int)
    case test1
}
var t3 = TestEnum3.test(10)
print(Mems.memStr(ofVal: &t3))
print((MemoryLayout<TestEnum3>.stride))//16
print(MemoryLayout<TestEnum3>.size)//9
print((MemoryLayout<TestEnum3>.alignment))//8

//switch的枚举关联值的底层实现:读取枚举变量的内存的成员值找到switch对应语句,并将成员值的前面内存值赋值给变量v1v2v3,跟case写在哪里没关系
var e0 = TestEnum0.test1(10, 20, 30)
switch e0 {
case let .test2(v1, v2):
    print("test2",v1, v2)
case let .test1(v1, v2, v3):
    print("test1",v1, v2, v3)
case let .test3(v1):
    print("test3",v1)
case let .test4(v1):
    print("test4",v1)
case .test5:
    print("test5")
}

/* 9.汇编
 r开头:64bit,8字节
 e开头:32bit,4字节
 ax,bx,cx:16bit,2字节
 ah,al:8bit,1字节
 */

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。下面详细介绍C语言的基本概念和语法。 1. 变量和数据类型 在C语言中,变量用于存储数据,数据类型用于定义变量的类型和范围。C语言支持多种数据类型,包括基本数据类型(如int、float、char等)和复合数据类型(如结构体、联合等)。 2. 运算符 C语言中常用的运算符包括算术运算符(如+、、、/等)、关系运算符(如==、!=、、=、<、<=等)、逻辑运算符(如&&、||、!等)。此外,还有位运算符(如&、|、^等)和指针运算符(如、等)。 3. 控制结构 C语言中常用的控制结构包括if语句、循环语句(如for、while等)和switch语句。通过这些控制结构,可以实现程序的分支、循环和多路选择等功能。 4. 函数 函数是C语言中用于封装代码的单元,可以实现代码的复用和模块化。C语言中定义函数使用关键字“void”或返回值类型(如int、float等),并通过“{”和“}”括起来的代码块来实现函数的功能。 5. 指针 指针是C语言中用于存储变量地址的变量。通过指针,可以实现对内存的间接访问和修改。C语言中定义指针使用星号()符号,指向数组、字符串和结构体等数据结构时,还需要注意数组名和字符串常量的特殊性质。 6. 数组和字符串 数组是C语言中用于存储同类型数据的结构,可以通过索引访问和修改数组中的元素。字符串是C语言中用于存储文本数据的特殊类型,通常以字符串常量的形式出现,用双引号("...")括起来,末尾自动添加'\0'字符。 7. 结构体和联合 结构体和联合是C语言中用于存储不同类型数据的复合数据类型。结构体由多个成员组成,每个成员可以是不同的数据类型;联合由多个变量组成,它们共用同一块内存空间。通过结构体和联合,可以实现数据的封装和抽象。 8. 文件操作 C语言中通过文件操作函数(如fopen、fclose、fread、fwrite等)实现对文件的读写操作。文件操作函数通常返回文件指针,用于表示打开的文件。通过文件指针,可以进行文件的定位、读写等操作。 总之,C语言是一种功能强大、灵活高效的编程语言,广泛应用于各种领域。掌握C语言的基本语法和数据结构,可以为编程学习和实践打下坚实的基础。
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值