美文网首页iOS底层
iOS-内存地址调用

iOS-内存地址调用

作者: xxxxxxxx_123 | 来源:发表于2020-02-26 20:40 被阅读0次

下面程序是否能够执行?为什么?

@interface TPerson : NSObject

- (void)eat;

@end

@implementation TPerson

- (void)eat {
    NSLog(@"==TPerson==eat====");
}


@end
TPerson *person = [[TPerson alloc] init];
[person eat];
    
id pcls = [TPerson class];
void *pp= &pcls;
[(__bridge id)pp eat];

解析,运行程序,控制台输出:

2020-02-21 17:46:54.530375+0800 005---Runtime应用[52965:2000889] ==TPerson==eat====
2020-02-21 17:46:54.530576+0800 005---Runtime应用[52965:2000889] ==TPerson==eat====

可以看到pp确实正常调用了方法,这是为什么呢?我们先来分析一下,person调用方法,person是一个对象,而对象的本质是个结构体,并且第一个元素是isaisa指向的是类对象。实例方法都是存在类中的,person能够调用方法,也是通过isa指向了类,从而从类的数据中找到了方法。

再来看看pclspcls指向的是TPerson的类对象,而指针pp又指向的是pcls的地址,这样也形成了一个指向关系:pp指向pcls,而pcls指向TPerson的类对象,也就可以正常调用方法了。

我们给TPerson添加一个属性:

@property (nonatomic, copy) NSString *name;

eat的实现改成以下:

- (void)eat {
    NSLog(@"==TPerson==eat=====name=%@==", self.name);
}

然后对代码做以下的修改:

// TPerson *person = [[TPerson alloc] init];
// [person eat];

id pcls = [TPerson class];
void *pp= &pcls;
[(__bridge id)pp eat];

运行程序,会发现控制台输出:

2020-02-21 19:23:51.188431+0800 005---Runtime应用[53411:2043433] ==TPerson==eat=====name=<ViewController: 0x7ff70f400760>==

这是为什么呢?然后我们上述注释的代码放开,运行程序,控制台输出:

2020-02-21 19:33:30.325806+0800 005---Runtime应用[53472:2047490] ==TPerson==eat=====name=(null)==
2020-02-21 19:33:30.326163+0800 005---Runtime应用[53472:2047490] ==TPerson==eat=====name=<TPerson: 0x60000129c700>==

在程序运行期间,执行代码就会不停的压栈-出栈操作。由于栈的地址是连续的,pp又是pcls的地址。第一次的时候,由于先调用[super viewDidLoad],我们的栈里已经压入了ViewController,当执行[(__bridge id)pp eat]的时候,需要获取self.name的值,而name占用8字节,由于name本身还没有初始化,也没有值,pp地址偏移8字节就会获取到之前压入栈里的ViewController。同理加入TPerson之后,偏移8字节获取到了TPerson

Tips: & 和 *

*是取值运算符,对地址使用可以获得地址中储存的数值。对于指针a*a表示取a中的值。

在调用时,*p是指针p指向的那个变量,比如:

int a = 5;
int *p = a;

那么p的值是a的地址,也就是指针p指向a*p则等于a的值,即*p=5

&是地址运算符,对变量使用可以获得该变量的地址。 对于变量b&b表示取b的地址。

&是引用,比如:

int a = 5;
int b = &a;

那么这里的b则引用a的值,即b=5,而再给b赋值:b=10a的值也会变为10。

相关文章

  • iOS-内存地址调用

    下面程序是否能够执行?为什么? 解析,运行程序,控制台输出: 可以看到pp确实正常调用了方法,这是为什么呢?我们先...

  • iOS-取消延迟执行的方法cancelPreviousPerfo

    前面写过一篇文章iOS-利用performSelector调用方法iOS-利用performSelector调用方...

  • Django-admin源码解析

    单例模式 前言:实例化出来的每个对象都是不同的内存地址,调用每个对象的方法都是调用同一块内存地址 —— ...

  • inline.内联函数

    引入内联函数是为了解决函数调用效率的问题由于函数之间的调用,会从一个内存地址调到另外一个内存地址,当函数调用完毕之...

  • iOS内存----内存布局(一)

    stack(栈):方法调用(内存地址向下增长)heap(堆):通过alloc等分配的对象(内存地址向上增长)bss...

  • 内联函数

    解决函数调用效率的问题:函数之间调用,是内存地址之间的调用,当函数调用完毕之后还会返回原来函数执行的地址。函数调用...

  • iOS之LLDB常用命令

    打印值、修改值、调用方法 p、po 打印值po:输出值p:输出值+值类型+引用名+内存地址(xcode中有内存地址...

  • c++入门 - 内联函数、#pragma once

    内联函数 函数的调用 执行到函数调用指令时,程序将在函数在调用后立即存储该指令的内存地址,并将函数参数复制到堆栈(...

  • 函数指针和void * 之间的转换

    函数指针函数名转换成内存地址调用 (*(void(*) ())0)();这是《C Traps and Pitfal...

  • iOS-调用方法

    在 iOS中可以直接调用某个对象的消息方式有两种: 利用performSelector 和NSInvocation...

网友评论

    本文标题:iOS-内存地址调用

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