指针
###普通指针:
int a = 10;// 在内存里有一个10;我们定义一个变量a ,把 10 赋值给变量a; 这个过程叫值拷贝;
int b = 10; //
LGNSLog(@"%d -- %p",a,&a);
LGNSLog(@"%d -- %p",b,&b);
打印结果:值是一样的,但是a,b 在内存里的地址是不一样哦。
10 -- 0x7ffeefbff4ac
10 -- 0x7ffeefbff4a8
Mark:&a --> int a = 10;
###对象:指针拷贝
实例化出来两个对象,这两个对象分别又被两个不同的指针指向着。
LGPerson *p1 = [LGPerson alloc];
LGPerson *p2 = [LGPerson alloc];
LGNSLog(@"%@ -- %p",p1,&p1);
LGNSLog(@"%@ -- %p",p2,&p2);
打印结果:
<LGPerson: 0x100693610> -- 0x7ffeefbff4a0
<LGPerson: 0x1006929f0> -- 0x7ffeefbff498
Mark:&p1 --->p1 ---> LGPerson
### 数组指针
int c[4] = {1,2,3,4};
int *d = c;
NSLog(@"%p - %p - %p",&c,&c[0],&c[1]);
NSLog(@"%p - %p - %p",d,d+1,d+2);
打印结果:
0x7ffeefbff4c0 - 0x7ffeefbff4c0 - 0x7ffeefbff4c4
0x7ffeefbff4c0 - 0x7ffeefbff4c4 - 0x7ffeefbff4c8
mark: 数组指针:数组的地址就是数组内第一个元素的指针地址。
第二次打印的数据 指针偏移;int 在内存中占 4个字节,所以每次都会加4.
for (int i = 0; i<4; i++) {
// int value = c[i];
int value = *(d+i);
LGNSLog(@"%d",value);
}
打印结果:1,2,3,4
使用指针打印数据;
我们也可以打印一下对象的内存结构
x/4gx 0x7ffeefbff4c0
0x7ffeefbff4c0: 0x0000000200000001 0x0000000400000003
0x7ffeefbff4d0: 0x00007ffeefbff4f0 0xfa3a5ced5c6300a3
------ 内存存储:小端存储;-------
类的结构是什么样的
class 继承自 objc_class ,objc_class 继承自 objc_object
类、对象:万物皆对象
1:typedef struct objc_class *Class;
2:结构:
struct objc_class : objc_object {
// Class ISA; // 8字节 --隐藏的class的ISA 是来源父类的 👇
Class superclass; // 8字节
cache_t cache; // 16 不是8 因为cache_t 是个指针 // formerly cache pointer and vtable
class_data_bits_t bits; // class_rw_t * plus custom rr/alloc flags
class_rw_t *data() {
return bits.data();
}.......and so on
/// Represents an instance of a class.
struct objc_object {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
};
父类的里面的class的ISA👆
3: class_rw_t 也是一个结构体 里面存放着
a: method_array_t
b: property_array_t
c: protocol_array_t
struct class_rw_t {
// Be warned that Symbolication knows the layout of this structure.
uint32_t flags;
uint32_t version;
const class_ro_t *ro;
method_array_t methods;
property_array_t properties;
protocol_array_t protocols;
Class firstSubclass;
Class nextSiblingClass;
char *demangledName;
#if SUPPORT_INDEXED_ISA
uint32_t index;
#endif
###nsobject:
@interface NSObject <NSObject> {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-interface-ivars"
Class isa OBJC_ISA_AVAILABILITY;
#pragma clang diagnostic pop
}
打印当前的对象的内存结构
LGPerson *person = [LGPerson alloc];
Class pClass = object_getClass(person);
x/4gx pClass
0x1000023b0: 0x001d800100002389 0x0000000100b37140
0x1000023c0: 0x00000001003da260 0x0000000000000000
Mark:0x001d800100002389 --->第一个是ISA
0x0000000100b37140 --->superclass
0x00000001003da260 ---> cache_t
0x0000000000000000 --->bits 未赋值的bits
这就是类的结构;
/**
define ISA_MASK 0x0000000ffffffff8ULL
**/
po 0x001d800100002389 & ISA_MASK 就是当前的ISA指向的类
po 0x001d800100002389 & 0x0000000ffffffff8
打印结果:
LGPerson
/-----------/
打印
po 0x1000023b8 从0x1000023b0 地址加8就是superclass
<NSObject: 0x1000023b8>
### class_data_bits_t :【**】
(lldb)x/4gx pClass
0x1000023d0: 0x001d8001000023a9 0x0000000100b37140
0x1000023e0: 0x00000001003da260 0x0000000000000000
(lldb)p (class_data_bits_t*)0x1000023f0
(class_data_bits_t *) $1 = 0x00000001000023f0
====
p $1->data()
(class_rw_t *) $2 = 0x0000000101020950
p *$2 看rw的存储结构
(class_rw_t) $3 = {
flags = 2148139008
version = 0
ro = 0x0000000100002328
methods = {
list_array_tt<method_t, method_list_t> = {
= {
list = 0x0000000100002260
arrayAndFlag = 4294976096
}
}
}
properties = {
list_array_tt<property_t, property_list_t> = {
= {
list = 0x0000000100002310
arrayAndFlag = 4294976272
}
}
}
protocols = {
list_array_tt<unsigned long, protocol_list_t> = {
= {
list = 0x0000000000000000
arrayAndFlag = 0
}
}
}
firstSubclass = nil
nextSiblingClass = NSUUID
demangledName = 0x0000000000000000
}
p $3.properties 里面是个二位数组
(property_array_t) $4 = {
list_array_tt<property_t, property_list_t> = {
= {
list = 0x0000000100002310
arrayAndFlag = 4294976272
}
}
}
p $4.list
(property_list_t *) $5 = 0x0000000100002310
p $5.first
(property_t) $6 = (name = "nickName", attributes = "T@\"NSString\",C,N,V_nickName")
Fix-it applied, fixed expression was:
$5->first
查看ro 存的东西
p *$3.ro
(const class_ro_t) $7 = {
flags = 388
instanceStart = 8
instanceSize = 24
reserved = 0
ivarLayout = 0x0000000100001f84 "\x02"
name = 0x0000000100001f7b "LGPerson"
baseMethodList = 0x0000000100002260
baseProtocols = 0x0000000000000000
ivars = 0x00000001000022c8
weakIvarLayout = 0x0000000000000000
baseProperties = 0x0000000100002310
}
p *$7.baseProperties ------>属性
(property_list_t) $8 = {
entsize_list_tt<property_t, property_list_t, 0> = {
entsizeAndFlags = 16
count = 1
first = (name = "nickName", attributes = "T@\"NSString\",C,N,V_nickName")
}
}
p *$7.ivars ----->-成员变量
(const ivar_list_t) $10 = {
entsize_list_tt<ivar_t, ivar_list_t, 0> = {
entsizeAndFlags = 32
count = 2
first = {
offset = 0x0000000100002398
name = 0x0000000100001e54 "hobby"
type = 0x0000000100001fa1 "@\"NSString\""
alignment_raw = 3
size = 8
}
}
}
p $10.get(1) -- 属性与成员变量的区别
(ivar_t) $11 = {
offset = 0x00000001000023a0
name = 0x0000000100001e5a "_nickName"
type = 0x0000000100001fa1 "@\"NSString\""
alignment_raw = 3
size = 8
}
属性 存在了 class -> objc_class -> class_data_bits_t -> property_list_t ->
class -> objc_class -> class_data_bits_t -> class_ro_t -> {
baseProperties,属性相关
ivars:成员变量
}
mark:objc_class 和NSObject 的区别
前者是底层的C的写法 NSObject 是oc的写法,是oc的封装方法;
网友评论