ios学习之旅---指针也不难

1、认识指针
#include <stdio.h>
//基本数据类型作为函数參数传递是值传递
//void moveFront(int x ,int y)
//{
//    x  = x + 2;
//}
void test()
{
    //  确定当前坐标
    int x = 20;
    int y = 150;
    printf("%p\n",&x);
    printf("%lu\n",&x);

    *((int *)(0x7fff5fbff76c)) = 22;
    printf("(%d,%d)\n",x,y);
    //    moveFront(x, y);
    //    printf("(%d,%d)\n",x,y);

}

//假设你想訪问指针所指向存储空间,就必须使用訪问指针所指向的存储空间的操作符
void moveFront(int *x ,int *y)
{
//  x  = x + 2;//此时是改变指针的指向,而不是訪问指针所指向的存储空间
    *x  = *x + 2;
}

int main(int argc, const char * argv[]) {

    //  确定当前坐标
    int x = 20;
    int y = 150;
    printf("(%d,%d)\n",x,y);
    moveFront(&x, &y);
    printf("(%d,%d)\n",x,y);

    return 0;
}

2、指针的定义与初始化(重点掌握)

内存中最小的存储单元:字节。每个字节在内存中都有一个编号,这编号就是指针

指针:内存地址

有了指针你就有了打开这块内存钥匙,就能够操作这一块内存

指针变量:存放内存地址的变量

定义指针:指针所指向数据类型  * 指针变量名称;

在的定义变量时候,*是一个类型说明符,说明定义这个变量是一个指针变量

在不是定义的变量的时候。*是一个操作符。訪问(读、写)指针所指向的那块存储空

指针的初始化:

注意点:

1、仅仅有定义没有初始化指针里面是一个垃圾值。这时候我们成为这个指针为野指针

2、假设操作一个野指针

2.1 程序崩溃

2.2 訪问不该你訪问存储。操作潜在逻辑错误

3、不能够使用整形常量赋值一个指针变量

由于内存是操作系统分配我们的,不是我们随便取的

4、什么类型的指针。仅仅指向什么类型的变量

5、多个指针能够指向同一变量

6、指针的指向是能够改变的

#include <stdio.h>

//指针的定义
void test()
{
    int num = 10;

    //  定义一个指针变量
    int *p;
    p = #

    *p = 20;
    printf("num = %d\n",num);
}

int main(int argc, const char * argv[]) {

// 先定义在进行初始化
    int num = 10;
//  定义一个指针变量p
    int * p;

//    *p = # // p 还有进行初始。不可以訪问它所指向存储空间
    p = #//p 指向 num
    *p = 20;

//  定义指针变量的同一时候进行初始

    int num2 = 20;

    int *p2 = &num2;

    *p2 = 40;

    printf("%d,%d\n",num2,*p2);

// 不可以使用整形常量赋值一个指针变量
// 由于内存是操作系统分配我们的,不是我们随便取的

//    int *p3 = 100000;//此处是错误的
//
//    *p3 = 10;

    p2 = #

    printf("%p\n",p2);

    char c = ‘a‘;

    int *pc = &c;

    *pc = 10;

    printf("%p\n",p2);

    return 0;
}

3、多级指针

通过指针訪问变量称为间接訪问。

因为指针变量直接指向变量,所以称为“一级指针”。而

假设通过指向指针的指针变量来訪问变量则构成“二级指针”。

#include <stdio.h>

void test()
{
    int num = 10;

    int *p = #

    //  定义一个指针来指向变量p
    //  pp就是一个二级指针
    int **pp = &p;

    **pp = 30;
    printf("%d\n",num);

    int ***ppp = &pp;
    ***ppp = 50;
    printf("%d\n",num);

    //  四级指针
    int ****pppp = &ppp;
    ****pppp = 100;
    printf("%d\n",num);
}
void readFile(char **error)
{
    *error = "读取错误";
}

int main(int argc, const char * argv[]) {

//    char error[100];

    char *error;

    readFile(&error);

    printf("%s",error);

    return 0;
}

4、指针为什么要区分类型

1、变量的地址是变量所在占存储空间的首地址

2、指针变量只能够存储一个地址编号,假设没有类型。当通过指针就不知道要訪问多少个字节的存储空间

3、指针区分类型是为了在通过指针訪问它所指向的存储空间的时候,可以正确訪问

4、假设通过一个char类型的指针操作一个int的变量。假设值的二进制数据超过1字节,那么就造成数据错误

5、假设通过一个int 类型的指针操作一个char变量,那么你就会改动了你不该改动的内存,造成程序逻辑错误

#include <stdio.h>
/*
   全部指针类型都是占用八个字节的存储空间

 */
void testEveryPointerIs8B()
{
    printf("%lu\n",sizeof(int *));
    printf("%lu\n",sizeof(char *));
    printf("%lu\n",sizeof(double *));
    printf("%lu\n",sizeof(float *));
    printf("%lu\n",sizeof(float **));
}

int main(int argc, const char * argv[]) {

    int num = 10;

    char *cp = #

    printf("%d\n",num);

    return 0;
}

5、指针运算概述

指针变量:存放是内存字节的地址编号(无符号的整形数)

指针:是运算受限的无符号的整形数

运算运算:

指针 + 整形数 === 指针变量中值 + sizeof(其所指向数据类型)

指针 - 整数数 === 指针变量中值 - sizeof(其所指向数据类型)

pointer1 - pointer2 = (pointer1中值 - pointer2中值) / sizeof(其指向数据类型)

赋值运算:

=

+= 必须是一个整形数

-= 必须是一个整形数

比較运算

==

!=

>

<

>=

<=

自增自减

p++; p = p + 1;

++p; p = p + 1;

--p;

p--;

#include <stdio.h>

//算术运算
void test()
{
    int a = 10;

    int *p = &a;
    //  指针+1
    p = p + 1;

    int nums[5] = {1,2,3,4,5};

    int * pointer1 = nums;

    int * pointer2 = &nums[4];

    size_t size  = pointer2 - pointer1;
    printf("%lu\n",size);
    //  pointer1 + pointer2;
    //    pointer2 * pointer1;
    //    pointer1 / pointer2;
    //    pointer1 / 2;
}
//赋值运算
void test1()
{
    int a = 10;

    //    int *p = &a;

    int nums[] = {1,2,3,4,5};

    int *p = nums;
    int *p2 = nums;
    p += 2;
    p = p + 2;

    p -= 1;

    printf("%d\n",*p);
}

//关系运算
int main(int argc, const char * argv[]) {

    int nums[] = {1,2,3,4,5};

    int *p = nums;
    p++;
    int result =  nums == p;
    result = p > nums;
    p--;
    result = p < nums;
    result = p >= nums;
    result = p <= nums;
    printf("%d\n",result);
    return 0;
}

6、指针与一维数组(理解)

数组像一个指针:訪问数组中元素,使用数组与使用指向这个数组的指针是等价

nums[1] ==== p[1]

nums+1  ==== p + 1;

nums[1] 的本质 *(nums + 1)

指针 + 整数 =====  指针中的值 + sizeof(所指向的数据类型) * 整数

//    int nums[] = {1,2,3,4,5};

//

//    int *p = nums;

double nums[] = {1.0,2.0,3,4,5};

double * p = nums;

//    printf("%d,%d,%d,%d,%d,%d\n",nums[1],p[1],*(nums + 1),*(p + 1),*(++p),。

);

printf("%p\n",nums);

printf("%p\n",nums+2);

printf("%p\n",p);

printf("%p\n",p+2);

数组不是一个指针

1、sizeof(array) != sizeof(pointer):当一个数组赋值一个指针变量的时候,那么数组中有些信息就丢失了,比方数组长度,这样的现象指针信息遗失

2、指针的指向是能够改变的,数组的指向是不能够改变

3、array == &array 数组名就是数组地址,pointer != &pointer : 指针所指向地址不是指针本身地址

#include <stdio.h>
int main(int argc, const char * argv[]) {
    int nums[] = {1,2,3,4,5};
    int *p = nums;
    p = nums;
//    nums = nums + 1;
     printf("%lu,%lu\n",sizeof(nums),sizeof(p));
    printf("%p\n",nums);
    printf("%p\n",&nums);
    printf("%p\n",p);
    printf("%p\n",&p);
    return 0;
}

7、指针与二维数组

指针数组与二维数组指针变量的差别

应该注意指针数组和二维数组指针变量的差别。这两者尽管都可用来表示二维数组,可是其表示方法和意义是

不同的。

二维数组指针变量是单个的变量,其一般形式中"(*指针变量名)"两边的括号不可少。而指针数组类型表示的

是多个指针(一组有序指针)在一般形式中"*指针数组名"两边不能有括号。

比如:

int (*p)[3];

表示一个指向二维数组的指针变量。该二维数组的列数为3或分解为一维数组的长度为3。

int *p[3]

表示p是一个指针数组,有三个下标变量p[0]。p[1],p[2]均为指针变量。

#include <stdio.h>

void test()
{

    int nums[3][2] = {{1,2},{3,4},{5,6}};
    int *p = nums[0];
    printf("%p\n",p);
    printf("%p\n",nums);
    for (int i = 1; i < 6; i++) {
        printf("%d ",*(p + i));
    }

}
/*
  定义指针数组的格式:
  数据类型 * 指针变量名称[指针个数]
 */
void test2()
{
    int nums[3][2] = {{1,2},{3,4},{5,6}};

    //    int * p[2] = {nums[0],nums[1]};
    //        p = nums;
    //
    //    printf("%d\n",p[0][1]);

    int a = 10;
    int b = 20;
    int c = 30;

    int *p = &a;

    //    *p === p[1]; 没有这么写的

    int *ps[3] = {&a,&b,&c};

    printf("%d,%d,%d",*ps[0],*ps[1],*ps[2]);

}
/*
  定义一个指向一维数组的指针
  数据类型 (*指针名称)[所指向的一维数组的元素个数]

  指针 + 整数 === 指针中的值 + 所指向数据类型的长度 * 整数
 */

int main(int argc, const char * argv[]) {

    int nums[3][2] = {{1,2},{3,4},{5,6}};

    int (*ps)[2];

    ps = nums;//能够觉得ps 与 nums是等价的
    int num = ps[0][1];
    printf("%d\n",num);
    printf("%p\n",nums);
    printf("%p\n",nums+1);
    printf("%p\n",ps);
    printf("%p\n",ps+1);
    for (int i =0 ; i < 3; i++) {

        for (int j = 0; j < 2 ; j++) {
            printf("%d ",ps[i][j]);
        }
        printf("\n");
    }

//    nums   nums[0]

//    同样点:相应地址都是一样的
//    不同点:指针类型是不同
//    nums + 1 = nums + sizeof(nums[0])
//    nums[0] + 1 = nums + sizeof(int)

//   sizeof(nums) 二维数组所用占用存储空间字节数
//   sizeof(nums) / sizeof(int) 二维数组中一共同拥有多少个int的数据

    int *p = nums[0];
    for (int i = 0; i < sizeof(nums) / sizeof(int); i++) {
        printf("%d ",p[i]);
    }

    return 0;
}
时间: 2024-10-19 00:07:21

ios学习之旅---指针也不难的相关文章

iOS学习之旅10 ATS(App Transport Security)对HTTPS协议要求引起的问题

问题描述 编写以下代码获取网络某个资源的MIMEType 1 -(void)getMIMEType 2 { 3 //路径 4 NSURL *url = [NSURL URLWithString:@"https://www.baidu.com/img/bd_logo1.png"]; 5 //请求对象 6 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; 7 NSOperationQueue *

IOS学习之路-- 指针&amp;宏函数

如果*p被()包住,说明指针变量p将来指向的是函数 //声明一个指针变量 //int (*p)(int, int) = sum; int (*p)(int, int); p = sum; // 如果*p被()包住,说明指针变量p将来指向的是函数 // 最左边的void说明p指向的函数没有返回值 // 最右边的()说明p指向的函数没有形参 void (*p)(); // 函数名test就是test函数的地址 // 将test函数的地址赋值给了指针变量p // 指针变量p成功指向了test函数 p

iOS学习之旅9 ZipArchive和SSZipArchive

SSZipArchive 简介 ZipArchive是iOS和Mac上一个简单实用的压缩和解压插件.用途包括:1.解压zip文件:2.解压密码保护的ZIP文件:3.创建新的zip文件:4.追加文件到现有的压缩:5.压缩文件:6.压缩NSData(带有文件名) ZipArchive的GitHub地址:https://github.com/ZipArchive/ZipArchive 压缩 dfad 解压 1221 ZipArchive 简介 dfdfdff 压缩 dfad 解压 1221

我的北京ios学习之旅03

来到北京第三个周了,这个周oc语言的学习也渐渐进入尾声了,帝都也真是热的不行,还好教室还是很凉快的.也熟悉的这边的日常生活和起居,渐渐的有了学习的样子. 周末还和骏哥一起去天安门玩了下,第一次去什么感觉也说不出来,反正就是累,转路还去了鸟巢和水立方,虽然没进去,只是远远的观望了下.也算留下脚印了.有时间还想去长城看看.老师讲课到了现在更是能感受细致的教学方式了,不用害怕基础差,只要努力我相信我一定能做好,学完OC和C,接下来就是更重要的了.继续努力加油.人生不需要多少计划,遇到就是缘分,碰上就是

ios学习之旅------玩转结构体

1.全局变量和局部变量 局部变量: 概念:定义函数内部变量 定义格式:变量类型 变量名称; 作用域:从定义那一行开始到所在代码块结束 生命周期:从代码执行到定义的哪一行开始,到其所在的代码的结束为止 特点:相同的代码块中不可以有同名的变量 不同的代码块中可以有同名的变量,内部的变量会覆盖外部定义的变量 全局变量: 概念:定义在函数外部变量 定义:变量类型 变量名称 = 值; 声明:变量类型 变量名称; 特点:1.不可以重复定义,但可以重复声明 2.局部变量可以与全局变量同名,在局部变量的作用域范

ios学习之旅--oc对象的关系

1.匿名对象:就是没有名字对象 1.匿名对象仅用一次 使用场景: 1.当我们仅仅要调用一个对象的某个方法一次的时候能够使用匿名对象 2.匿名对象能够作为函数的实际參数 #import <Foundation/Foundation.h> #import "CZPerson.h" #import "CZBook.h" @interface CZBook : NSObject @end @implementation CZBook @end @interfac

iOS学习之旅7 NSBundle的pathForResource:ofType: 返回值为nil问题

在处理XML的过程中,在项目中手动创建名为“data.xml”的文件,加入网上找的内容 <?xml version="1.0" encoding="utf-8"?> <Dogs> <Dog id="001"> <name>Ryan</name> <age>26</age> </Dog> <Dog id="002"> &l

IOS学习之旅-Swift-函数

//----------------    函数    --------------------------- //func为函数名关键字 //一个参数 //func+函数名+(参数名:参数类型)-> 返回类型 func sayHello(personName: String) -> String { let test = "hello," + personName + "!" return test } println(sayHello("p

IOS学习之旅-UI基础设置

#import "ViewController.h" @interface ViewController () //声明顺序:全局变量.属性.方法 - (void)initailizeUserInterface; //初始化用户界面 @end - (void)initailizeUserInterface; //初始化用户界面 @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; [