//
//  main.m
//  NSObjectTest
//
//  Created by 马家欣 on 2020/8/26.
//  Copyright © 2020 马家欣. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "MyObject.h"
#import "MySubObject.h"
//#   __arm64__   define ISA_MASK        0x0000000ffffffff8ULL
//#   __x86_64__  define ISA_MASK        0x00007ffffffffff8ULL
@interface Test : NSObject
@end
@implementation Test
@end
int main(int argc, const char * argv[]) {
    struct A {
        long ccc;
        int value;
    };
//    int *a = {10, 11};
    @autoreleasepool {
//        B.a = [10];
        struct A *B = malloc(sizeof(struct A));
        B->value = 100;
        // insert code here...
        NSLog(@"Hello, World!");
        NSObject *obj = [[NSObject alloc] init];
//        struct objc_object { isa_t isa } * obj
        printf("\n ------------------------ 准备工作 ----------------------------\n");
        printf("  obj 是啥            : [obj.description UTF8String]   = %s\n",[obj.description UTF8String]);
        printf("  obj 地址            : &obj                           = %p\n",&obj);
        printf("  obj 的值（指向的地址） : obj                           = %p\n",obj);
        printf("  *obj 的地址         : &*obj                          = %p\n",&*(void **)(__bridge void*)obj);
        printf("  *obj 的值           : *obj                          = %p\n",*(void **)(__bridge void*)obj);
        printf("\n ---------------------- 拿到 obj.isa --------------------------\n");
        printf("拿到 isa： \n");
        printf("  ∵ typedef struct objc_object NSObject \n");
        printf("  ∴ obj 为 struct objc_object { isa_t isa } * obj\n");
        printf("  ∵ isa_t 为 objc_object 第一个元素， 长度刚好为 8 字节 \n");
        printf("  ∴ *obj（struct objc_object 第一个 8 字节的值）刚就是 isa_t的值\n");
        printf("  ∴ 只是因为 isa_t isa 刚好是第一块内存地址， 并且刚好 8 字节， *obj 刚好指向 isa\n");
        printf("  ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ \n");
        printf("  obj.isa = %p\n",*(void **)(__bridge void*)obj);
        printf("\n -------------------- 找到 obj.isa 的指向 ------------------------\n");
        unsigned long long int objc_isa = *(unsigned long long *)(__bridge void*)obj;
        printf("  obj.class name                    = %s\n",[obj.className UTF8String]);
        printf("  [NSObject Class] （指向的地址）     = %p\n",[NSObject class]);
        printf("  obj.class (指向的地址）             = %p\n",obj.class);
        printf("  obj.isa  &  ISA_MASK             = %p\n",(void *)(objc_isa & 0x00007ffffffffff8ULL));
        printf("  ∴ obj.isa 指向的地址等同于 obj.class 指向的地址, 等同于 [NSObject class] 指向的地址\n");
        printf("  ps. 不能理解为 obj.isa 指向 obj.class（因为这个玩意也是个指针）,他们刚好指向的地址一致 \n");
        printf("\n ------------------- 拿到 obj.class 的 isa：-----------------------\n");
        void * objClass = (void *)(objc_isa & 0x00007ffffffffff8ULL);
        unsigned long long int obj_isa_isa = *(unsigned long long int *)objClass;
        printf("  *obj.class    = %p\n",*(void **)(__bridge void*)obj.class);
        printf("  objc.isa.isa  = %p\n",(void *)obj_isa_isa);
        printf("  objc.isa.isa  ==  *obj.class \n");
        printf("\n ------------ 找到 obj.class.isa(obj.isa.isa) 的指向：----------------\n");
        printf("  *NSObject.class（既 NSObject.class.isa）   = %p\n",*(void **)(__bridge void*)(NSObject.class));
        printf("  obj.isa.isa 指向的地址                      = %p\n",(void *)obj_isa_isa);
        printf("  obj.isa.isa & ISA_MASK                    = %p\n",(void *)(obj_isa_isa & 0x00007ffffffffff8ULL));
        printf("  可以看到 *objc.isa.isa == obj.isa.isa, class 的 isa 中除了指针外不再带其他信息\n");
        
        void * objMetaClass = (void *)(obj_isa_isa & 0x00007ffffffffff8ULL);
        unsigned long long int obj_isa_isa_isa = *(unsigned long long int *)objMetaClass;
        printf("  obj_isa_isa_isa & ISA_MASK                    = %p\n",obj_isa_isa_isa);
        printf("  obj_isa_isa_isa & ISA_MASK                    = %p\n",(void *)(obj_isa_isa_isa & 0x00007ffffffffff8ULL));
        printf("  ps： \n");
        printf("  不能用 [[obj class] class] 输出 MetaClass， 因为一个是类方法，一个是实例方法\n");
        printf("  [obj class] = NSObject      是 - class 的实现 \n");
        printf("  [NSObject class] = NSObject 是 + class 的实现 \n");
        printf("  同理 [[NSObject class] class] 输出的就是 NSObject\n");
        printf("  两个是不同的函数， 所以没办法用这种方式打出 MetaClass \n");
        
        
        printf("\n\n ============================================================\n");
        printf("\n ------------------- NSObject SubClass -----------------------\n");
        MyObject *myObject = [MyObject alloc];
        void * myObjectISA = *(void **)(__bridge void *)myObject;
        void * myObjectISA_ISA = *(void **)((unsigned long long)myObjectISA & 0x00007ffffffffff8ULL);
        // METAMyObject
        void * myObjectISA_ISA_ISA = *(void **)((unsigned long long)myObjectISA_ISA & 0x00007ffffffffff8ULL);
        printf("myObject              name             :     %s\n",[myObject.description UTF8String]);
        printf("myObject              address          :     %p\n",&myObject);
        printf("[myObject superclass] name             :     %s\n",[[[myObject superclass] className] UTF8String]);
        printf("[myObject superclass] value            :     %p\n",[myObject superclass]);
//        printf("[myObject superclass] address          :     %p\n",&(__bridge void*)[myObject superclass]);
        printf("[myObject className]  name             :     %s\n",[[myObject className] UTF8String]);
        printf("[myObject class]      address          :     %p\n",[myObject class]);
        printf("myObject.isa          address          :     %p\n",myObjectISA);
        printf("myObject.isa & MASK = [myObject class] :     %p\n",(unsigned long long)myObjectISA & 0x00007ffffffffff8ULL);
        printf("myObject.isa.isa      address          :     %p\n",myObjectISA_ISA);
        printf("myObject.isa.isa & MASK = NSObject     :     %p\n",(unsigned long long)myObjectISA_ISA & 0x00007ffffffffff8ULL);
        
        
        
        
        
        printf("myObject class          %p\n",myObject.class);
        printf("myObject class isa(meta)           %p\n",*(void **)(__bridge void*)myObject.class);
        printf("myObject class isa & MASK    %p\n",*(unsigned long long *)(__bridge void*)myObject.class & 0x00007ffffffffff8ULL);
        printf("myObject superclass     %p\n",myObject.superclass);
        printf("myObject superclass     %p\n",myObject.superclass);
        printf("==========================\n");
        MySubObject *mySubObject = [MySubObject alloc];
        printf("mySubObject             %p\n",mySubObject);
        printf("mySubObject isa         %p\n",*(void **)(__bridge void*)mySubObject);
        printf("mySubObject class       %p\n",mySubObject.class);
        printf("mySubObject superclass  %p\n",mySubObject.superclass);
        printf("==========================\n");
        
        
    }
    return 0;
}
