String是Swift的常见结构,下面来动手分析
let s1 = "abc" as String
test(s:s1)
let s2 = "abcabcabcabcabcabcabcabcabcabc" as String
test(s:s2)
let s3 = "bcd" as StaticString
test(s:s3)
let s4 = "bcdbcdbcdbcdbcdbcdbcdbcdbcdbcd" as StaticString
test(s:s4)
其伪代码如下:
v14.n128_u64[0] = 6513249LL;
v16 = &_sSSN;
v14.n128_u64[1] = -2089670227099910144LL;
v1 = __swift_instantiateConcreteTypeFromMangledName(&_ss23_ContiguousArrayStorageCyypGMD);
v2 = v1;
v3 = swift_allocObject(v1, 64LL, 7LL);
v4 = v3;
*(_OWORD *)(v3 + 16) = xmmword_100006BE0;
_sypWOc(&v14, v3 + 32);
_ss5print_9separator10terminatoryypd_S2StF(v4, 32LL, -2233785415175766016LL, 10LL, -2233785415175766016LL);
swift_release(v4);
__swift_destroy_boxed_opaque_existential_0(&v14);
v14.n128_u64[0] = -3458764513820540898LL;
v16 = &_sSSN;
v14.n128_u64[1] = (unsigned __int64)"" | 0x8000000000000000LL;
v5 = swift_allocObject(v2, 64LL, 7LL);
v6 = v5;
*(_OWORD *)(v5 + 16) = xmmword_100006BE0;
_sypWOc(&v14, v5 + 32);
_ss5print_9separator10terminatoryypd_S2StF(v6, 32LL, -2233785415175766016LL, 10LL, -2233785415175766016LL);
swift_release(v6);
__swift_destroy_boxed_opaque_existential_0(&v14);
v7 = vdupq_n_s64(3uLL);
v16 = &_ss12StaticStringVN;
v7.n128_u64[0] = (unsigned __int64)"bcd";
v14 = v7;
v15 = 2;
v8 = swift_allocObject(v2, 64LL, 7LL);
v9 = v8;
*(_OWORD *)(v8 + 16) = xmmword_100006BE0;
_sypWOc(&v14, v8 + 32);
_ss5print_9separator10terminatoryypd_S2StF(v9, 32LL, -2233785415175766016LL, 10LL, -2233785415175766016LL);
swift_release(v9);
__swift_destroy_boxed_opaque_existential_0(&v14);
v16 = &_ss12StaticStringVN;
v10 = vdupq_n_s64(0x1EuLL);
v10.n128_u64[0] = (unsigned __int64)"bcdbcdbcdbcdbcdbcdbcdbcdbcdbcd";
v14 = v10;
v15 = 2;
v11 = swift_allocObject(v2, 64LL, 7LL);
v12 = v11;
*(_OWORD *)(v11 + 16) = xmmword_100006BE0;
_sypWOc(&v14, v11 + 32);
_ss5print_9separator10terminatoryypd_S2StF(v12, 32LL, -2233785415175766016LL, 10LL, -2233785415175766016LL);
经过调试分析,可以知道String类大小为16字节,在函数传参中默认以值传递(X0/X1),而返回时也以值传递(X0/X1),可以得到如下结构。可以看到String结构在长度<=15时使用short方式存储,长度>=16时使用long方式存储。使用long方式存储时,还有存在偏移,不知道为何如此设计。从总体看形似std::string结构,但是更复杂。
struct Swift.StaticString {
int64_t _addr; // 指向实际字符串
int64_t _len;
};
union Swift.String {
struct {
char _buf[15]; // 实际字符串
int _type : 4; // short的type=0xe
int _len : 4; // 字符串长度
} short,
struct {
int64_t _len : 60; // 字符串长度
int64_t _type : 4; // long的type=0xd
int64_t _addr; // (_addr&0x7ffffffffffffffff)+0x20指向实际字符串,最高位固定为1
} long
}