发布于2021-06-07 20:30 阅读(1151) 评论(0) 点赞(23) 收藏(5)
- func testFunc() {
- print("test method")
- }
- func makeIncrementer() -> () -> Int {
- var runningTotal = 10
- func incrementer() -> Int{
- runningTotal += 1
- return runningTotal
- }
- return incrementer
- }
- var t = { (age:Int) in
- return age
- }
- let b = t(20)
- print(b) // 20
- { (parameters) -> return type in
- statements
- }
- // 此处参数为Int类型 -> 返回值类型也为Int
- var a = { (param:Int) -> Int in
- return param+1
- }
- var closure:((Int) -> Int)?
- closure = { (param:Int) -> Int in
- return param+1
- }
- print(closure?(10) ?? 0)//11
- closure = nil //可置空
- //由于当前的闭包表达式被定义为变量、所以赋值之后还可以再次更改。如果为let则不可再次更改
- closure = { (param:Int) -> Int in
- return param * param
- }
- print(closure?(10) ?? 0)//100
- func closureTest(param:() -> Int){
- print(param()) //25
- }
- var age:Int = 20
- closureTest { () -> Int in //尾随闭包
- age+=5
- return age
- }
- func closureAfter(_ a: Int, _ b: Int, _ c: Int, by: (_ item1: Int, _ item2: Int, _ item3: Int) -> Bool) -> Bool{
- return by(a, b, c)
- }
- closureAfter(10, 20, 30,by:{ (_ item1:Int, _ item2:Int, _ item3:Int) -> Bool in
- return item1 + item2 < item3
- })
- closureAfter(10, 20, 30){ (_ item1:Int, _ item2:Int, _ item3:Int) -> Bool in
- return item1 + item2 < item3
- }
1、省略参数类型
- closureAfter(10, 20, 30) { (item1, item2, item3) -> Bool in
- return item1 + item2 < item3
- }
2、省略by参数闭包的返回值
- closureAfter(10, 20, 30) { (item1, item2, item3) in
- return item1 + item2 < item3
- }
3、省略 return 关键字
- closureAfter(10, 20, 30) { (item1, item2, item3)in
- item1 + item2 < item3
- }
4、省略参数名称及 in、使用 $0、$1、$2来表示参数
closureAfter(10, 20, 30) { return $0 + $1 < $2 }
5、继续省略 return关键字
closureAfter(10, 20, 30) { $0 + $1 < $2}
- var array = [1,2,4,3,0]
- array = array.sorted(by: <)
- print(array) //[0, 1, 2, 3, 4]
- func makeIncrementer() -> () -> Int {
- var runningTotal = 10
- func incrementer() -> Int{
- runningTotal += 1
- return runningTotal
- }
- return incrementer
- }
- let makeInc = makeIncrementer()//将返回函数传给常量 makeInc
- print(makeInc()) //11
- print(makeInc()) //12
- print(makeInc()) //13
- //然而直接调用三次的结果却为
- print(makeIncrementer()()) //11
- print(makeIncrementer()()) //11
- print(makeIncrementer()()) //11
结果为什么不一样呢?这里我们引入捕获值
- // makeIncrementer()
- sil hidden @main.makeIncrementer() -> () -> Swift.Int : $@convention(thin) () -> @owned @callee_guaranteed () -> Int {
- bb0: //alloc_box 创建一个变量给我们当前的变量 runningTotal、相当于把一个引用地址给了我们的 runningTotal,意味着当前的变量放到了我们当前的堆上
- %0 = alloc_box ${ var Int }, var, name "runningTotal" // users: %8, %7, %6, %1
- //project_boc取出创建好的这个变量
- %1 = project_box %0 : ${ var Int }, 0 // user: %4
- %2 = integer_literal $Builtin.Int64, 10 // user: %3
- %3 = struct $Int (%2 : $Builtin.Int64) // user: %4
- store %3 to %1 : $*Int // id: %4
- // function_ref incrementer #1 () in makeIncrementer()
- //在调用过程中、这个创建好的变量就传递给了我们的闭包来使用
- %5 = function_ref @incrementer #1 () -> Swift.Int in main.makeIncrementer() -> () -> Swift.Int : $@convention(thin) (@guaranteed { var Int }) -> Int // user: %7
- //闭包调用开始、对这个对象做了强引用计数+1操作
- strong_retain %0 : ${ var Int } // id: %6
- //闭包调用过程
- %7 = partial_apply [callee_guaranteed] %5(%0) : $@convention(thin) (@guaranteed { var Int }) -> Int // user: %9
- //对这个对象做了强引用计数的-1操作
- strong_release %0 : ${ var Int } // id: %8
- return %7 : $@callee_guaranteed () -> Int // id: %9
- } // end sil function 'main.makeIncrementer() -> () -> Swift.Int'
综上总结:
- func makeIncrementer() -> () -> Int {
- var runningTotal = 10
- func incrementer() -> Int{
- runningTotal += 1
- return runningTotal
- }
- return incrementer
- }
- let makeInc = makeIncrementer()
- print(makeInc())
- (lldb) po makeInc
- (Function)
- iN //N位的整型值
- i1 //一位整数。
- i8 //一个8位的整型:也就是1字节
- i32 //一个32位整数:4字节
- half //16位浮点值
- float //32位浮点值
- double //64位浮点值
- fp128 //128位浮点值
- [<# elements> x <elementtype>] //elements是一个恒定的整数值;elementtype可以是任何大小的类型。
- alloca [24 x i8],algin 8 //24个8位整型值都是0的数组
- [40 x i32] //40个32位整型值的数组。
- [4 x i8] //4个8位整型值的数组。
- [3 x [4 x i32]] //3x4的32位整型值数组。
- [12 x [10 x float]] //12x10的单精度浮点值数组。
- %T1 = type { <type list> } ; //正常结构体类型
- %T2 = type <{ <type list> }> ; //封装结构体类型
- //swift.refcounted结构体: 第一个元素为 swift.type类型的指针,第二位为64位整型值(8字节)
- %swift.refcounted = type { %swift.type*,i64 }
- { i32, i32, i32 } //三组32位整形值
- { float, i32 (i32) * } //第一个元素为浮点型,第二个元素是一个指向函数的指针:该函数参数为32位整型值,返回32位整型值
- <{ i8, i32 }> //被定义为一个5字节大小的封装结构体
- <type> *
- i64* //指向 i64类型 的指针
- [4 x i32]* //指向 4个i32类型的数组 的指针
- i32 (i32*) * //指向 参数为i32、返回值为i32的函数 的指针
- i32 addrspace(5)* //指向 在内存地址5中的i32类型 的指针
- <result> = getelementptr <ty>, <ty>* <ptrval>{, [inrange] <ty> <idx>}*
- <result> = getelementptr inbounds <ty>, <ty>* <ptrval>{, [inrange] <ty> <idx>}*
- <result> = getelementptr <ty>, <ptr vector> <ptrval>, [inrange] <vector index type> <idx>
- struct munger_struct {
- int f1;
- int f2;
- };
- void munge(struct munger_struct *p){
- p[0].f1 = p[1].f1 + p[2].f2;
- }
- struct munger_struct array[3];
- //int main(int argc, const char * argv[]) {
- // munge(array); //将结构体数组传递给函数
- // return 0;
- //}
- clang main.c -emit-llvm -S -c -o main.ll //LLVM IR 生成指令
- clang StructIR/main.c -emit-llvm -S -c -o main.ll > ./main.ll && open main.ll //案例中生成并打开文件的指令
- //1、定义了一个struct.munger_struct 的结构体 = 第一个参数为 i32,第二个参数也为 i32
- %struct.munger_struct = type { i32, i32 }
- //2、自定义的全局数组:3个 struct.munger_struct结构体类型的数组、并初始化
- @array = common global [3 x %struct.munger_struct] zeroinitializer, align 16
-
- define void @munge(%struct.munger_struct* %0) #0 {
- //5、%2创建了一片内存空间、存放的是我们当前 struct.munger_struct结构体 的地址: 所以当前的%2是一个地址的地址(二级指针)
- %2 = alloca %struct.munger_struct*, align 8
- //由%struct.munger_struct** %2 可见 %2 二级指针
- store %struct.munger_struct* %0, %struct.munger_struct** %2, align 8
- // %3 = 当前数组的首地址
- %3 = load %struct.munger_struct*, %struct.munger_struct** %2, align 8
- //8、访问当前的p[1] : 当前index = 1,1 x 结构体大小(4字节)、访问我们数组当中的第二个元素p[1]
- %4 = getelementptr inbounds %struct.munger_struct, %struct.munger_struct* %3, i64 1
- //9、访问数组中第二个结构体的第一个成员f1
- %5 = getelementptr inbounds %struct.munger_struct, %struct.munger_struct* %4, i32 0, i32 0
- //14、 %6 = 访问 p[1].f1
- %6 = load i32, i32* %5, align 4
- //15、当前数组的首地址
- %7 = load %struct.munger_struct*, %struct.munger_struct** %2, align 8
- //10、访问当前的p[2]: 当前的 index = 2, 2 x 结构体大小(4字节),访问我们数组中的第三个元素p[2]
- %8 = getelementptr inbounds %struct.munger_struct, %struct.munger_struct* %7, i64 2
- //11、访问数组中的第三个结构体的第二个成员f2
- %9 = getelementptr inbounds %struct.munger_struct, %struct.munger_struct* %8, i32 0, i32 1
- //16、 %10 = 访问 p[2].f2
- %10 = load i32, i32* %9, align 4
- //17、 %11 = p[1].f1+p[2].f2
- %11 = add nsw i32 %6, %10
- //4、 %12 访问的是我们的 %2。 6、取出%2的首地址给%12;此时%12存放的是当前数组的首地址
- %12 = load %struct.munger_struct*, %struct.munger_struct** %2, align 8
- //3、 当前返回值类型位 %struct.munger_struct结构体类型、需要拿到数组的基地址,%struct.munger_struct* %12是当前索引结构体的地址、i64 0 当前数组的index;
- %13 = getelementptr inbounds %struct.munger_struct, %struct.munger_struct* %12, i64 0 //12、访问当前数组的第一个元素p[0]
- //7、%13 是我们当前数组的第一个结构体元素;第一个i32 0 相当于结构体指针偏移0字节,也就是不偏移,第二个i32 0 表示第一个结构体成员
- %14 = getelementptr inbounds %struct.munger_struct, %struct.munger_struct* %13, i32 0, i32 0 //13、访问数组中第一个结构体的第一个成员f1
- //18、 p[0].f1 = p[1].f1+p[2].f2
- store i32 %11, i32* %14, align 4
- ret void
- }
- int main(int argc, const char * argv[]) {
- int array[4] = {1, 2, 3, 4};
- int a = array[0];
- return 0;
- }
- //其中 int a = array[0] 这句对应的LLVM代码应该是这样的:
- %6 = alloca [4 x i32], align 16
- %9 = getelementptr inbounds [4 x i32], [4 x i32]* %6, i64 0, i64 0
- define i32 @main(i32 %0, i8** %1) #0 {
- entry:
- %2 = bitcast i8** %1 to i8*
- %3 = call swiftcc { i8*, %swift.refcounted* } @"main.makeIncrementer() -> () -> Swift.Int"()
- ....
- }
- define hidden swiftcc { i8*, %swift.refcounted* } @"main.makeIncrementer() -> () -> Swift.Int"() #0 {
- entry:
- %runningTotal.debug = alloca %TSi*, align 8
- %0 = bitcast %TSi** %runningTotal.debug to i8*
- call void @llvm.memset.p0i8.i64(i8* align 8 %0, i8 0, i64 8, i1 false)
- //3、由swift_allocObject 分配出来的HeapObject对象 给到 %1
- %1 = call noalias %swift.refcounted* @swift_allocObject(%swift.type* getelementptr inbounds (%swift.full_boxmetadata, %swift.full_boxmetadata* @metadata, i32 0, i32 2), i64 24, i64 7) #1
- //4、将 %1 转换为 <{ %swift.refcounted, [8 x i8] }>*指针类型、其中又包含了一个swift.refcounted结构体,并且分配了 8xi8也就是8字节内存空间、该空间存储的也就是我们的数值
- %2 = bitcast %swift.refcounted* %1 to <{ %swift.refcounted, [8 x i8] }>* //9、<{ %swift.refcounted, [8 x i8] }>结构体为当前所创建出来的box
- %3 = getelementptr inbounds <{ %swift.refcounted, [8 x i8] }>, <{ %swift.refcounted, [8 x i8] }>* %2, i32 0, i32 1
- //7、连续的8字节地址空间
- %4 = bitcast [8 x i8]* %3 to %TSi*
- store %TSi* %4, %TSi** %runningTotal.debug, align 8
- //6、%TSi 为当前数组;数组的指针%TSi*; 第一个i32 0为TSi*类型首地址、第二个i32 0 取其中的第一个元素 i8
- %._value = getelementptr inbounds %TSi, %TSi* %4, i32 0, i32 0
- //5、将 i64 类型的数值 10 存储到 %._value中; 8、相当于将 10 存放到连续的8字节内存地址空间中
- store i64 10, i64* %._value, align 8
- %5 = call %swift.refcounted* @swift_retain(%swift.refcounted* returned %1) #1
- call void @swift_release(%swift.refcounted* %1) #1
- //2、往 { i8*, %swift.refcounted* } 插入值;bitcast:unsafeBitCast按位转换、把当前的内嵌函数incrementr #1 () -> Swift.Int (i64)转换为 i8*
- //也就是放入void * 8字节内存空间中、意味着当前的void *存的是我们内嵌函数的地址;%swift.refcounted* %1,1 又插入一个 %1;
- //10、也就是将%1的HeapObject对象放到了结构体数据中
- %6 = insertvalue { i8*, %swift.refcounted* } { i8* bitcast (i64 (%swift.refcounted*)* @"partial apply forwarder for incrementr #1 () -> Swift.Int in main.makeIncrementer() -> () -> Swift.Int" to i8*), %swift.refcounted* undef }, %swift.refcounted* %1, 1
- //1、函数调用后返回值的结果为一个结构体:第一个元素为 i8类型的指针(理解为 void*),第二个元素为 swift.refcounted 结构体类型的指针。并将 %6 该结构体类型返回
- ret { i8*, %swift.refcounted* } %6
- }
- %swift.function = type { i8*, %swift.refcounted* }
- %swift.refcounted = type { %swift.type*, i64 } // { (i64)* , i64} 该结构也就是我们的HeapObject对象
- %swift.type = type { i64 }
- %swift.full_type = type { i8**, %swift.type }
- %swift.full_boxmetadata = type { void (%swift.refcounted*)*, i8**, %swift.type, i32, i8* }
- %swift.bridge = type opaque
- %Any = type { [24 x i8], %swift.type* }
- %TSi = type <{ i64 }>
- struct HeapObject {
- var type:UnsafeRawPointer
- var refCount:UInt64
- }
- struct FunctionData<BoxType>{
- var ptr:UnsafeRawPointer
- var captureValue:BoxType //BoxType代表范型T
- }
- struct Box<T> {
- var refCounted:HeapObject
- var value:T
- }
- //这里必须包裹一层、不然当前的函数类型被当作泛型参数传递之后会被重新包裹一层;
- struct VoidIntFunc {//包装一个f、使我们的返回值不受影响
- var f: () -> Int //makeIncrementer() 的返回值
- }
- var makeInc = VoidIntFunc(f:makeIncrementer())
- let ptrr = UnsafeMutablePointer<FunctionData<Box<Int>>>.allocate(capacity: 1)
- //Cannot convert value of type 'VoidIntFunc' to expected argument type 'FunctionData<Box<Int>>'
- ptrr.initialize(to: makeInc)
- var makeInc = VoidIntFunc(f:makeIncrementer())
- var ptr = UnsafeMutablePointer<VoidIntFunc>.allocate(capacity: 1)
- ptr.initialize(to: makeInc)
- let context = ptr.withMemoryRebound(to: FunctionData<Box<Int>>.self, capacity: 1) {
- $0.pointee
- }
- print(context.ptr) //0x00000001000056a0
- print(context.captureValue.value) //7307466919713137513
- print("end")//断点
- $ nm ~/Library/Developer/Xcode/DerivedData/StructIR-alsccwttwgnzaobtshifjxvyffzg/Build/Products/Debug/ClosureInner | grep 00000001000056a0
- 00000001000056a0 t _$s12ClosureInner15makeIncrementerSiycyF10incrementrL_SiyFTA
- $ nm ~/Library/Developer/Xcode/DerivedData/StructIR-alsccwttwgnzaobtshifjxvyffzg/Build/Products/Debug/ClosureInner | grep 00000001000056a0 | xcrun swift-demangle
- 00000001000056a0 t partial apply forwarder for incrementr #1 () -> Swift.Int in ClosureInner.makeIncrementer() -> () -> Swift.Int
- func debugOutPrint(_ condition:Bool ,_ message:String) {
- if condition {
- print("\(message)")
- }
- }
- debugOutPrint(ture, "Application Error Occured") //Application Error Occured
- func debugOutPrint(_ condition:Bool ,_ message:String) {
- if condition {
- print("\(message)")
- }
- }
- func doSomething() -> String {
- print("test method")
- return "Application Error Occured"
- }
- debugOutPrint(false, doSomething()) //test method
- func debugOutPrint(_ condition:Bool ,_ message: () -> String) {
- if condition {
- print(message())
- }
- }
- func doSomething() -> String {
- print("doSomething method")
- return "Application Error Occured"
- }
- debugOutPrint(false, doSomething) //
- debugOutPrint(true, doSomething) //doSomething method \n Application Error Occured
- debugOutPrint(true, doSomething())
- debugOutPrint(true, "Application Error Occured")
- { //大概酱紫
- "Application Error Occured String"
- }
- func debugOutPrint(_ condition:Bool ,_ message: @autoclosure () -> String) {
- if condition {
- print(message())
- }
- }
- func doSomething() -> String {
- print("doSomething method")
- return "Application Error Occured"
- }
- debugOutPrint(true, doSomething())
- debugOutPrint(true, "Application Error Occured String")
- doSomething method
- Application Error Occured
- Application Error Occured String
作者:临摹
链接:http://www.phpheidong.com/blog/article/89474/eff301a7a92a7f8830b3/
来源:php黑洞网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
---无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事,而不是让内心的烦躁、焦虑,坏掉你本来就不多的热情和定力
Copyright © 2018-2021 php黑洞网 All Rights Reserved 版权所有,并保留所有权利。 京ICP备18063182号-4
投诉与举报,广告合作请联系vgs_info@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!