美文网首页
数组存储的探索(C/OC/Swift)

数组存储的探索(C/OC/Swift)

作者: 小曼blog | 来源:发表于2019-06-12 10:49 被阅读0次

    声明:这是一篇探索类文章,因作者知识局限,并不一定是正确的结论,小编抱着不懂就要问的心态,写出博客是为了大家讨论,答疑解惑,抛砖引玉,欢迎广大程序员们一起讨论。

    偶然间在一本数据结构的书上看到说数组在计算机中是顺序存储的,也就是地址是连续的,就想验证一下。当然了,这本书是以C语言为基本语言的,我记忆中,C语言的数组的确是连续的地址,不过,别的语言呢?是否也是连续的呢?手边有电脑,试试看呗。

    C语言的数组

    //
    //  main.c
    //  Array_C
    //
    //  Created by weiman on 2019/6/12.
    //  Copyright © 2019 weiman. All rights reserved.
    //
    
    #include <stdio.h>
    
    int main(int argc, const char * argv[]) {
        // insert code here...
        printf("Hello, World!\n");
        
        int array[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        for (int i = 0; i < 10; i++) {
            printf("array[%d] = %d 地址: %p\n", i, array[i], &array[I]);
        }
        
        printf("\n\n");
        
        char array2[5] = {'a', 'b', 'c', 'd', 'e'};
        for (int i = 0; i < 5; i++) {
            printf("array[%d] = %c 地址: %p\n", i, array2[i], &array2[I]);
        }
        
        printf("\n\n");
        
        char array3[] = {"I am a lady, I like code."};
        long len = strlen(array3);
        for (int i = 0; i < len; i++) {
            printf("array[%d] = %c 地址: %p\n", i, array3[i], &array3[I]);
        }
        
        return 0;
    }
    
    

    打印结果:

    Hello, World!
    array[0] = 1 地址: 0x7ffeefbff560
    array[1] = 2 地址: 0x7ffeefbff564
    array[2] = 3 地址: 0x7ffeefbff568
    array[3] = 4 地址: 0x7ffeefbff56c
    array[4] = 5 地址: 0x7ffeefbff570
    array[5] = 6 地址: 0x7ffeefbff574
    array[6] = 7 地址: 0x7ffeefbff578
    array[7] = 8 地址: 0x7ffeefbff57c
    array[8] = 9 地址: 0x7ffeefbff580
    array[9] = 10 地址: 0x7ffeefbff584
    
    
    array[0] = a 地址: 0x7ffeefbff527
    array[1] = b 地址: 0x7ffeefbff528
    array[2] = c 地址: 0x7ffeefbff529
    array[3] = d 地址: 0x7ffeefbff52a
    array[4] = e 地址: 0x7ffeefbff52b
    
    
    array[0] = I 地址: 0x7ffeefbff540
    array[1] =   地址: 0x7ffeefbff541
    array[2] = a 地址: 0x7ffeefbff542
    array[3] = m 地址: 0x7ffeefbff543
    array[4] =   地址: 0x7ffeefbff544
    array[5] = a 地址: 0x7ffeefbff545
    array[6] =   地址: 0x7ffeefbff546
    array[7] = l 地址: 0x7ffeefbff547
    array[8] = a 地址: 0x7ffeefbff548
    array[9] = d 地址: 0x7ffeefbff549
    array[10] = y 地址: 0x7ffeefbff54a
    array[11] = , 地址: 0x7ffeefbff54b
    array[12] =   地址: 0x7ffeefbff54c
    array[13] = I 地址: 0x7ffeefbff54d
    array[14] =   地址: 0x7ffeefbff54e
    array[15] = l 地址: 0x7ffeefbff54f
    array[16] = i 地址: 0x7ffeefbff550
    array[17] = k 地址: 0x7ffeefbff551
    array[18] = e 地址: 0x7ffeefbff552
    array[19] =   地址: 0x7ffeefbff553
    array[20] = c 地址: 0x7ffeefbff554
    array[21] = o 地址: 0x7ffeefbff555
    array[22] = d 地址: 0x7ffeefbff556
    array[23] = e 地址: 0x7ffeefbff557
    array[24] = . 地址: 0x7ffeefbff558
    Program ended with exit code: 0
    

    小编实验了整型数组、字符型数组和字符串数组,从打印的结果来看,的确是连续的地址。就整型数组来说,每个整型元素占四个字节,而地址打印也是四字节为梯度的。小编窃以为,可以得出结论:

    C语言的数组的确是连续的存储空间。数组的长度等于每个元素的大小乘以元素个数。

    OC的数组

    OC的数组NSArray是继承自NSObject的一个类,所有声明的数组都是一个对象。 数组中存储的类型也是对象,而不能直接存储简单数据类型(int, float等)。

    //
    //  main.m
    //  Array_OC
    //
    //  Created by weiman on 2019/6/12.
    //  Copyright © 2019 weiman. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            // insert code here...
            NSLog(@"Hello, World!");
            
            //整数对象的数组
            NSArray * array = @[@1, @2, @3, @4, @5, @6, @7, @8, @9, @10];
            for (int i = 0; i < array.count; i++) {
                NSLog(@"array[%d] = %@, 地址:%p", i, array[i], array[I]);
            }
            
            NSLog(@"\n");
            
            //字符对象数组
            NSArray * array2 = @[@'a', @'b', @'c', @'d', @'e'];
            for (int i = 0; i < array2.count; i++) {
                NSLog(@"array[%d] = %c, 地址:%p", i, [array2[i] charValue], array2[I]);
                //NSLog(@"类型: %@", [array2[i] class]);
            }
            
            NSLog(@"\n");
            
            //字符串数组
            NSArray * array3 = @[@"today", @"is", @"a", @"good", @"day", @"!"];
            for (int i = 0; i < array3.count; i++) {
                NSLog(@"array[%d] = %@, \t 地址:%p", i, array3[i], array3[I]);
            }
            
        }
        return 0;
    }
    
    

    打印结果:

    2019-06-12 11:37:12.936390+0800 Array_OC[1121:37990] Hello, World!
    2019-06-12 11:37:12.936854+0800 Array_OC[1121:37990] array[0] = 1, 地址:0x1932fd5ba595cea1
    2019-06-12 11:37:12.936902+0800 Array_OC[1121:37990] array[1] = 2, 地址:0x1932fd5ba595cda1
    2019-06-12 11:37:12.936937+0800 Array_OC[1121:37990] array[2] = 3, 地址:0x1932fd5ba595cca1
    2019-06-12 11:37:12.936968+0800 Array_OC[1121:37990] array[3] = 4, 地址:0x1932fd5ba595cba1
    2019-06-12 11:37:12.937002+0800 Array_OC[1121:37990] array[4] = 5, 地址:0x1932fd5ba595caa1
    2019-06-12 11:37:12.937036+0800 Array_OC[1121:37990] array[5] = 6, 地址:0x1932fd5ba595c9a1
    2019-06-12 11:37:12.937116+0800 Array_OC[1121:37990] array[6] = 7, 地址:0x1932fd5ba595c8a1
    2019-06-12 11:37:12.937156+0800 Array_OC[1121:37990] array[7] = 8, 地址:0x1932fd5ba595c7a1
    2019-06-12 11:37:12.937190+0800 Array_OC[1121:37990] array[8] = 9, 地址:0x1932fd5ba595c6a1
    2019-06-12 11:37:12.937224+0800 Array_OC[1121:37990] array[9] = 10, 地址:0x1932fd5ba595c5a1
    2019-06-12 11:37:12.937250+0800 Array_OC[1121:37990] 
    2019-06-12 11:37:12.937306+0800 Array_OC[1121:37990] array[0] = a, 地址:0x1932fd5ba595ae81
    2019-06-12 11:37:12.937336+0800 Array_OC[1121:37990] array[1] = b, 地址:0x1932fd5ba595ad81
    2019-06-12 11:37:12.937363+0800 Array_OC[1121:37990] array[2] = c, 地址:0x1932fd5ba595ac81
    2019-06-12 11:37:12.937390+0800 Array_OC[1121:37990] array[3] = d, 地址:0x1932fd5ba595ab81
    2019-06-12 11:37:12.937418+0800 Array_OC[1121:37990] array[4] = e, 地址:0x1932fd5ba595aa81
    2019-06-12 11:37:12.937435+0800 Array_OC[1121:37990] 
    2019-06-12 11:37:12.937496+0800 Array_OC[1121:37990] array[0] = today,   地址:0x1000020d8
    2019-06-12 11:37:12.941546+0800 Array_OC[1121:37990] array[1] = is,      地址:0x1000020f8
    2019-06-12 11:37:12.941632+0800 Array_OC[1121:37990] array[2] = a,       地址:0x100002118
    2019-06-12 11:37:12.941667+0800 Array_OC[1121:37990] array[3] = good,    地址:0x100002138
    2019-06-12 11:37:12.941707+0800 Array_OC[1121:37990] array[4] = day,     地址:0x100002158
    2019-06-12 11:37:12.941738+0800 Array_OC[1121:37990] array[5] = !,       地址:0x100002178
    Program ended with exit code: 0
    

    第二次打印:

    2019-06-12 11:43:18.514574+0800 Array_OC[1128:39111] Hello, World!
    2019-06-12 11:43:18.514971+0800 Array_OC[1128:39111] array[0] = 1, 地址:0x3c37d6152e5c911d
    2019-06-12 11:43:18.515017+0800 Array_OC[1128:39111] array[1] = 2, 地址:0x3c37d6152e5c921d
    2019-06-12 11:43:18.515052+0800 Array_OC[1128:39111] array[2] = 3, 地址:0x3c37d6152e5c931d
    2019-06-12 11:43:18.515083+0800 Array_OC[1128:39111] array[3] = 4, 地址:0x3c37d6152e5c941d
    2019-06-12 11:43:18.515144+0800 Array_OC[1128:39111] array[4] = 5, 地址:0x3c37d6152e5c951d
    2019-06-12 11:43:18.515188+0800 Array_OC[1128:39111] array[5] = 6, 地址:0x3c37d6152e5c961d
    2019-06-12 11:43:18.515225+0800 Array_OC[1128:39111] array[6] = 7, 地址:0x3c37d6152e5c971d
    2019-06-12 11:43:18.515258+0800 Array_OC[1128:39111] array[7] = 8, 地址:0x3c37d6152e5c981d
    2019-06-12 11:43:18.515291+0800 Array_OC[1128:39111] array[8] = 9, 地址:0x3c37d6152e5c991d
    2019-06-12 11:43:18.515323+0800 Array_OC[1128:39111] array[9] = 10, 地址:0x3c37d6152e5c9a1d
    2019-06-12 11:43:18.515340+0800 Array_OC[1128:39111] 
    2019-06-12 11:43:18.515374+0800 Array_OC[1128:39111] array[0] = a, 地址:0x3c37d6152e5cf13d
    2019-06-12 11:43:18.515459+0800 Array_OC[1128:39111] array[1] = b, 地址:0x3c37d6152e5cf23d
    2019-06-12 11:43:18.515520+0800 Array_OC[1128:39111] array[2] = c, 地址:0x3c37d6152e5cf33d
    2019-06-12 11:43:18.515550+0800 Array_OC[1128:39111] array[3] = d, 地址:0x3c37d6152e5cf43d
    2019-06-12 11:43:18.515578+0800 Array_OC[1128:39111] array[4] = e, 地址:0x3c37d6152e5cf53d
    2019-06-12 11:43:18.515595+0800 Array_OC[1128:39111] 
    2019-06-12 11:43:18.515656+0800 Array_OC[1128:39111] array[0] = today,   地址:0x1000020d8
    2019-06-12 11:43:18.515697+0800 Array_OC[1128:39111] array[1] = is,      地址:0x1000020f8
    2019-06-12 11:43:18.515725+0800 Array_OC[1128:39111] array[2] = a,       地址:0x100002118
    2019-06-12 11:43:18.515751+0800 Array_OC[1128:39111] array[3] = good,    地址:0x100002138
    2019-06-12 11:43:18.515777+0800 Array_OC[1128:39111] array[4] = day,     地址:0x100002158
    2019-06-12 11:43:18.515802+0800 Array_OC[1128:39111] array[5] = !,       地址:0x100002178
    Program ended with exit code: 0
    

    关闭Xcode,再次打开项目,查看打印结果:

    2019-06-12 11:48:16.162621+0800 Array_OC[1151:40460] Hello, World!
    2019-06-12 11:48:16.163089+0800 Array_OC[1151:40460] array[0] = 1, 地址:0xb2e9877e5f00a3e1
    2019-06-12 11:48:16.163133+0800 Array_OC[1151:40460] array[1] = 2, 地址:0xb2e9877e5f00a0e1
    2019-06-12 11:48:16.163161+0800 Array_OC[1151:40460] array[2] = 3, 地址:0xb2e9877e5f00a1e1
    2019-06-12 11:48:16.163190+0800 Array_OC[1151:40460] array[3] = 4, 地址:0xb2e9877e5f00a6e1
    2019-06-12 11:48:16.163228+0800 Array_OC[1151:40460] array[4] = 5, 地址:0xb2e9877e5f00a7e1
    2019-06-12 11:48:16.163262+0800 Array_OC[1151:40460] array[5] = 6, 地址:0xb2e9877e5f00a4e1
    2019-06-12 11:48:16.163300+0800 Array_OC[1151:40460] array[6] = 7, 地址:0xb2e9877e5f00a5e1
    2019-06-12 11:48:16.163339+0800 Array_OC[1151:40460] array[7] = 8, 地址:0xb2e9877e5f00aae1
    2019-06-12 11:48:16.163371+0800 Array_OC[1151:40460] array[8] = 9, 地址:0xb2e9877e5f00abe1
    2019-06-12 11:48:16.163395+0800 Array_OC[1151:40460] array[9] = 10, 地址:0xb2e9877e5f00a8e1
    2019-06-12 11:48:16.163408+0800 Array_OC[1151:40460] 
    2019-06-12 11:48:16.163440+0800 Array_OC[1151:40460] array[0] = a, 地址:0xb2e9877e5f00c3c1
    2019-06-12 11:48:16.163465+0800 Array_OC[1151:40460] array[1] = b, 地址:0xb2e9877e5f00c0c1
    2019-06-12 11:48:16.163489+0800 Array_OC[1151:40460] array[2] = c, 地址:0xb2e9877e5f00c1c1
    2019-06-12 11:48:16.163513+0800 Array_OC[1151:40460] array[3] = d, 地址:0xb2e9877e5f00c6c1
    2019-06-12 11:48:16.163532+0800 Array_OC[1151:40460] array[4] = e, 地址:0xb2e9877e5f00c7c1
    2019-06-12 11:48:16.163544+0800 Array_OC[1151:40460] 
    2019-06-12 11:48:16.167522+0800 Array_OC[1151:40460] array[0] = today,   地址:0x1000020d8
    2019-06-12 11:48:16.167553+0800 Array_OC[1151:40460] array[1] = is,      地址:0x1000020f8
    2019-06-12 11:48:16.167573+0800 Array_OC[1151:40460] array[2] = a,       地址:0x100002118
    2019-06-12 11:48:16.167597+0800 Array_OC[1151:40460] array[3] = good,    地址:0x100002138
    2019-06-12 11:48:16.167624+0800 Array_OC[1151:40460] array[4] = day,     地址:0x100002158
    2019-06-12 11:48:16.167650+0800 Array_OC[1151:40460] array[5] = !,       地址:0x100002178
    Program ended with exit code: 0
    

    从打印结果,是否可以得出如下结论:

    OC中的数组元素地址不一定是顺序存储的,但是地址却是紧挨着的。
    由于OC中的数组元素都是对象,打印的也是对象的地址,也就是指针,指针在内村中占8个字节,所以地址变化的都是最后三位。

    Swift的数组

    有别于OC和C,Swift的数组既不是基本数据类型,也不是对象,而是结构体。


    image.png

    在Swift中,尽量弱化指针的使用,常用的数组、字典、集合甚至Int、Float等类型都是结构体。

    思考:swift为什么把那么多类型设计成结构体呢?反过来想,OC为什么要把那么多类型设计成类?C语言的数据类型设计的初衷又是什么呢?

    (小编知识实在有限,还没有想明白为什么,希望了解的各路大神给予指点。)

    回归主题,来看看Swift中,数组的打印结果又是怎样的呢?

    //
    //  main.swift
    //  Array_Swift
    //
    //  Created by weiman on 2019/6/12.
    //  Copyright © 2019 weiman. All rights reserved.
    //
    
    import Foundation
    
    print("Hello, World!")
    
    let array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    for var num in array {
        print("\(num), \(withUnsafePointer(to: &num, {$0}))")
    }
    
    print("\n\n")
    
    let array2 = ["a", "b", "c", "d", "e"]
    for var str in array2 {
        print("\(str), \(withUnsafePointer(to: &str, {$0}))")
    }
    
    print("\n\n")
    
    let array3 = ["I", "am", "studying", "now", ".", "please", "call", "me", "later"]
    for var str in array3 {
        print("\(str), \(withUnsafePointer(to: &str, {$0}))")
    }
    
    

    打印结果:

    Hello, World!
    1, 0x00007ffeefbff420
    2, 0x00007ffeefbff420
    3, 0x00007ffeefbff420
    4, 0x00007ffeefbff420
    5, 0x00007ffeefbff420
    6, 0x00007ffeefbff420
    7, 0x00007ffeefbff420
    8, 0x00007ffeefbff420
    9, 0x00007ffeefbff420
    10, 0x00007ffeefbff420
    
    
    
    a, 0x00007ffeefbff458
    b, 0x00007ffeefbff458
    c, 0x00007ffeefbff458
    d, 0x00007ffeefbff458
    e, 0x00007ffeefbff458
    
    
    
    I,        0x00007ffeefbff4a0
    am,       0x00007ffeefbff4a0
    studying, 0x00007ffeefbff4a0
    now,      0x00007ffeefbff4a0
    .,        0x00007ffeefbff4a0
    please,   0x00007ffeefbff4a0
    call,     0x00007ffeefbff4a0
    me,       0x00007ffeefbff4a0
    later,    0x00007ffeefbff4a0
    Program ended with exit code: 0
    

    观察发现,Swift中,数组的元素地址都是一个。我们是否可以得出如下结论:

    Swift中,数组是一个结构体,它所包含的元素也就存储于这个结构体中,是这个结构体的一部分。数组的元素地址也是同一个。

    那么,swift中数组元素的地址会不会跟数组的地址相同呢?我们在打印一下数组的地址:

    Hello, World!
    1, 0x00007ffeefbff3a8
    2, 0x00007ffeefbff3a8
    3, 0x00007ffeefbff3a8
    4, 0x00007ffeefbff3a8
    5, 0x00007ffeefbff3a8
    6, 0x00007ffeefbff3a8
    7, 0x00007ffeefbff3a8
    8, 0x00007ffeefbff3a8
    9, 0x00007ffeefbff3a8
    10, 0x00007ffeefbff3a8
    array的地址:
    0x00000001000042a0
    
    
    
    a, 0x00007ffeefbff3e0
    b, 0x00007ffeefbff3e0
    c, 0x00007ffeefbff3e0
    d, 0x00007ffeefbff3e0
    e, 0x00007ffeefbff3e0
    array2的地址:
    0x00000001000042a8
    
    
    
    I, 0x00007ffeefbff420
    am, 0x00007ffeefbff420
    studying, 0x00007ffeefbff420
    now, 0x00007ffeefbff420
    ., 0x00007ffeefbff420
    please, 0x00007ffeefbff420
    call, 0x00007ffeefbff420
    me, 0x00007ffeefbff420
    later, 0x00007ffeefbff420
    array3的地址:
    0x00000001000042b0
    Program ended with exit code: 0
    

    结果发现,并不是同一个地址。

    思考:Swift中的数组元素到底是如何存储的呢?

    希望路过的大神们答疑解惑,文中如有错误,请批评指正,不胜感激。😁

    相关文章

      网友评论

          本文标题:数组存储的探索(C/OC/Swift)

          本文链接:https://www.haomeiwen.com/subject/oojkfctx.html