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;
}

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

  1. IOS学习之路-- 指针&宏函数

    如果*p被()包住,说明指针变量p将来指向的是函数 //声明一个指针变量 //int (*p)(int, int) = sum; int (*p)(int, int); p = sum; // 如果* ...

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

    1.匿名对象:就是没有名字对象     1.匿名对象仅用一次     使用场景:     1.当我们仅仅要调用一个对象的某个方法一次的时候能够使用匿名对象 2.匿名对象能够作为函数的实际參数 #imp ...

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

    1.全局变量和局部变量 局部变量:     概念:定义函数内部变量     定义格式:变量类型 变量名称;     作用域:从定义那一行開始到所在代码块结束     生命周期:从代码运行到定义的哪一行 ...

  4. ios学习之旅---c语言函数

    1.函数的概述 C源程序是由函数组成的. 尽管在前面各章的程序中大都仅仅有一个主函数main(),但有用程序往往由多个 函数组成. 函数是C源程序的基本模块,通过对函数模块的调用实现特定的功能. C语 ...

  5. 黑苹果-IOS学习的开始

    深知安装黑苹果的不易,在这里写一下关于我的Thinkpad E430c安装黑苹果教程(Mac版本:Yosemite 10.10.4),希望能够帮助有需要的朋友. 首先贴上我的电脑配置报表: ----- ...

  6. IOS学习【前言】

    2016-1-14 16年开始时导师安排任务,开始IOS学习之旅  经过几天的学习,感觉还是需要作比较多的学习笔记,因此开始用博客记录整个过程,方便以后查看学习与分享. 主要记录一些关键的问题处理方法 ...

  7. 【原】iOS学习47之第三方-FMDB

    将 CocoaPods 安装后,按照 CocoaPods 的使用说明就可以将 FMDB 第三方集成到工程中,具体请看博客iOS学习46之第三方CocoaPods的安装和使用(通用方法) 1. FMDB ...

  8. iOS学习路线图

    一.iOS学习路线图   二.iOS学习路线图--视频篇       阶 段 学完后目标 知识点 配套学习资源(笔记+源码+PPT) 密码 基础阶段 学习周期:24天       学习后目标:    ...

  9. 180分钟的python学习之旅

    最近在很多地方都可以看到Python的身影,尤其在人工智能等科学领域,其丰富的科学计算等方面类库无比强大.很多身边的哥们也提到Python非常的简洁方便,比如用Django搭建一个见得网站只需要半天时 ...

随机推荐

  1. Python学习日记之文件读取操作

    Python内置了文件读写的函数open,read 用法示例: open('/home/root/files.txt ') 在打开文件后,操作完成后可以使用close()关闭文件,但比较好的文件读写方 ...

  2. U盘安装完美的WIN7操作系统教程

    准备工作 首先备份或者在官网下载好您机器的驱动,否则完成后可能无法正常使用 ①一个有win7或者XP系统的电脑(制作启动盘用) ②一个4G以上的U盘 ③win7&win8系统包(请到官网下载或 ...

  3. (转)淘淘商城系列——商品搜索功能Service实现

    http://blog.csdn.net/column/details/15737.html 首先我们在taotao-search-interface工程中新建一个SearchService接口,并在 ...

  4. MFC_1.1 基本知识

    如何创建一个MFC项目 选择 MFC 应用程序进行创建,不要使用非英文名 选择对话框风格进行编写 可以通过自定义的设置修改类名 MFC 的基本知识 MFC 是纯面向对象的编程,是 SDK 经过 C++ ...

  5. C# 创建与读写配置文件

    配置文件内容为 <?xml version="1.0" encoding="utf-8" ?> <configuration> < ...

  6. Django线上部署教程:腾讯云+Ubuntu+Django+Uwsgi(转载)

    网站名称: 向东的笔记本 本文链接: https://www.eastnotes.com/post/29 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议.转载请注明出处! ...

  7. 牛客多校Round 8

    Solved:2 rank:164 签了两个oeis,但这样真的开心嘛

  8. nginx+keepalived+tomcat+memcache实现双VIP高可用及Session会话保持

    Nginx+Keepalived+Tomcat+Memcached 实现双VIP负载均衡及Session会话保持 IP 信息列表: 名称         IP                      ...

  9. ProgressDialog的样式

    ProgressDialog的样式有两种,一种是圆形不明确状态,一种是水平进度条状态 第一种方式:圆形进度条 final ProgressDialog dialog = new ProgressDia ...

  10. HDU - 2050 - 折线分割平面(数学 + dp)

    题意: 我们看到过很多直线分割平面的题目,今天的这个题目稍微有些变化,我们要求的是n条折线分割平面的最大数目.比如,一条折线可以将平面分成两部分,两条折线最多可以将平面分成7部分 思路: 记住结论.. ...