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

2019-06-12  本文已影响0人  小曼blog

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

偶然间在一本数据结构的书上看到说数组在计算机中是顺序存储的,也就是地址是连续的,就想验证一下。当然了,这本书是以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中的数组元素到底是如何存储的呢?

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

上一篇下一篇

猜你喜欢

热点阅读