美文网首页
玩转指针与地址

玩转指针与地址

作者: LuisX | 来源:发表于2018-04-15 17:28 被阅读55次
    计算机的核心部件:
    • 中央处理器(CPU)
    • 随机存储器(RAM)
      • 相当于海量的“开关”,中央处理器可以打开、关闭、访问这些开关。
      • 1 个开关保存一位(bit)的信息
      • 8 个开关保存一个字节(Byte)的信息
        • 1 代表(开)
        • 0 代表(关)
    内存与CPU
    地址
    • 内存是有数字编号的
    • 通常地址用来指代某个特定字节的数据
    32位CPU 和 64位CPU
    • 地址的大小不同
    • 32位CPU一次能处理32位,4个字节的数据
    • 64位CPU一次能处理64位,8个字节的数据
    如何获取数据起始位置的地址?

    程序在计算机运行时,相关的一切数据都会保存在内存中,并有各自的地址。
    运算符:&
    说明符:%p
    输出格式:十六进制

    #import <Foundation/Foundation.h>
    
    int main(int argc, char *argv[]) {
        @autoreleasepool {
            int i = 10;
            printf("变量i, 内存地址是 %p\n", &i);
            printf("函数main, 内存地址是 %p\n", main);
        }
    }
    // 变量i, 内存地址是 0x7ffeee0b855c
    // 函数main, 内存地址是 0x101b47ed0
    

    指针

    为什么非要使用指针呢?
    当遇到比较复杂的数据时,就很有必要用指针来传递地址了

    1.很容易地通过数据的起始地址,存取数据。
    2.程序不一定能通过拷贝来传递数据。
    3.程序一定能通过拷贝、直接传递数据的起始地址。

    1.用指针保存地址

    *星号,用于声明指针

    #import <Foundation/Foundation.h>
    
    int main(int argc, char *argv[]) {
        @autoreleasepool {      
            int i = 10;
            int *p = &i;
            printf("变量i, 内存地址是 %p\n", &i);
            printf("指针p, 内存地址是 %p\n", p);
        }
    }
    // 变量i, 内存地址是 0x7ffee10b155c
    // 指针p, 内存地址是 0x7ffee10b155c
    
    2.通过地址访问数据

    *星号,用于访问某个地址的数据, 也成为去引用。

    #import <Foundation/Foundation.h>
    
    int main(int argc, char *argv[]) {
        @autoreleasepool {      
            int i = 10;
            int *p = &i;
            printf("变量i, 内存地址是 %p\n", &i);
            printf("指针p, 内存地址是 %p\n", p);
            printf("指针p, 数据是 %d\n", *p);
        }
    }
    // 变量i, 内存地址是 0x7ffeee52c55c
    // 指针p, 内存地址是 0x7ffeee52c55c
    // 指针p, 数据是 10
    
    3.通过地址保存数据

    *星号,用于赋值表达式中

    #import <Foundation/Foundation.h>
    
    int main(int argc, char *argv[]) {
        @autoreleasepool {      
            int i = 10;
            int *p = &i;
            printf("变量i, 内存地址是 %p\n", &i);
            printf("指针p, 内存地址是 %p\n", p);
            printf("指针p, 数据是 %d\n", *p);
            *p = 123;
            printf("指针p, 数据是 %d\n", *p);
            printf("变量i, 数据是 %d\n", i);
        }
    }
    // 变量i, 内存地址是 0x7ffee9e5e55c
    // 指针p, 内存地址是 0x7ffee9e5e55c
    // 指针p, 数据是 10
    // 指针p, 数据是 123
    // 变量i, 数据是 123
    

    不同类型数据占用字节大小

    使用sizeof()可以获取某个数据类型的大小

    某个特定类型的数据会占用多少字节?sizeof()会返回一个类型为size_t的数
    说明符:%zu
    输出单位:byte
    指针长度:

    • 4字节,32位CPU
    • 8字节,64位CPU
    #import <Foundation/Foundation.h>
    
    int main(int argc, char *argv[]) {
        @autoreleasepool {      
            int i = 10;
            int *p = &i;
            printf("变量i, 占用字节是 %zu\n", sizeof(i));
            printf("指针p, 占用字节是 %zu\n", sizeof(p));
        }
    }
    // 变量i, 占用字节是 4
    // 指针p, 占用字节是 8
    

    空指针(NULL)

    “空”指针 不指向任何地址,用于明确表示该指针没有指向任何地址。

    NULL就是0(地址其实也是数字)
    nil 和 NULL 是相等的
    Objective-C 中使用 nil 来代表该地址上没有对象

    #import <Foundation/Foundation.h>
    
    int main(int argc, char *argv[]) {
        @autoreleasepool {      
            float *a;
            a = NULL;
            if (a) {
                printf("a 不是 NULL");
            } else {
                printf("a 是 NULL");
            }
        }
    }
    // a 是 NULL
    

    指针声明的代码规范

    每次加深对指针的理解,保持良好的代码风格。

    #import <Foundation/Foundation.h>
    
    int main(int argc, char *argv[]) {
        @autoreleasepool {
            // 编译会通过,代码风格不够好        
            float *one; // 正确
            float* two; // 错误
            
            // C 语言,允许一行代码生成多个变量
            float x, y, z;
            
            // 同时声明b,c为指针
            float* b, c; // 错误,(b指向float 的指针,c的类型是float)
            float *b *c; // 正确
        }
    }
    

    相关文章

      网友评论

          本文标题:玩转指针与地址

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