什么是指针?

指针就是一个地址,在c语言中任何东西都是有地址的,如何获取地址? 用的是&:取地址符

  • 指针就是一个整数

  • 获取指针:&

  • 定义变量时,可以通过取地址符 &,得到当前变量的地址-> 一个房间对应一个房间号,地址类比于房间号

  • 所有的指针类型都是 4个字节,就是一个整数,不需要考虑溢出

指针变量

存放地址(指针)的,也就是存放一个特定的整数(这个整数是可以表示地址的)

例:整型变量存放整数,指针变量存放指针,指针变量就是一个变量,和整型变量没有区别

  • 如何产生一个指针变量

  • * 用于标识 变量是 指针变量,必须有,没有就不是指针变量,* 写前面 和 写后面没有区别

类型* 变量名;

类型 *变量名;

  • 指针变量的两个重要概念

    • 指针的类型:去掉变量名

    • 指针所指向的类型:去掉变量名和 * 号

用指针的时候需要保持上述两个类型的一致

int* p;
//类型: int*
//所指向的类型: int    --->本质就是指针所操作的数据类型int(*pp)[3];   //--->指针
//类型: int(*)[3];
//所指向的类型: int[3] --->pp操作的就是一个数组 数组长度是3
int* pArray[3];//--->数组

第一个位置存储了一个0,0是4个字节,对应这四个字节的首地址就是这个地址:0x0000000EAA93F574-> 指针

#include <stdio.h>
int main()
{int num = 0;          //定义的变量会占用一段内存-> 操作系统对于这段内存会给予一个编号-> 地址//printf("%d\n", &num); //得到变量的地址:-1433143948-> 指针是一个整数printf("%p\n", &num);   //指针有特定的打印方式:0000000EAA93F574-> %p的方式打印 16进制的整数int* p;                    //指针变量char* pc;double* pd;printf("%d\n", sizeof(int*));printf("%d\n", sizeof(char*));void* pvoid;       pc = NULL;pd = NULL;pvoid = NULL;pc = (void*)0;         //强制转换语法-> 把0强制转换成一个地址赋值给一个指针变量//新手误区int* pNum = &num;       //在创建指针变量赋值的时候,不能这样理解*pNum=&num *起说明作用 int* 是一个类型//实质还是:pNum=&num;int aa = 1001;pNum = &aa;printf("%d\n", *pNum);  //得到当前地址中的值//当指针变量指向了普通变量的时候  *指针变量等效普通变量*pNum = 10111101;       //等效于普通变量做赋值运算 打印变量时变量改变了aa=10111101printf("%d\n", aa);return 0;
}/*输出*/8    //x64
8
1001
10111101
8    //x86
8
1001
10111101#ifndef NULL#ifdef __cplusplus#define NULL 0#else#define NULL ((void *)0)#endif
#endif

不同类型的指针变量

  • 所有类型的指针占用的字节数都是相同的-> 指针变量就是用来存放地址的,地址就是一个整数,所有整数占用内存都是一样的

  • 所有类型的指针变量占用的内存 在32位系统(x86)下都是4个字节   在64位系统(x64)下是8个字节

  • 特殊的指针类型:void*

  • 所有类型的指针变量的初始化都可以让它指向空

  • 专门用来初始化指针变量的东西:NULL

    • 防止悬浮指针:没有指向任何地方,放在那里,不知道它指向哪里

    • 防止野指针:指向一个莫名其妙的地方

    • 在写程序的时候一定要避免这两种情况的存在

  • 指针变量如何获取当前地址中的值:*指针变量

指针的运算

  • *指针变量:获取当前指针变量所指向的内存中存储的值

  • p+n操作或者p-n操作:算术运算,n是一个整数,实质上是内存的字节偏移,和指向内存存储的数据类型有关

    • p+sizeof(指针所指向的类型)*n

    • 对于一个指针变量来说,不会单独的去偏移,一般要指向一段内存去做偏移(数组就是一段连续的内存,可以通过指针的偏移去操作数组)

    • 对于不同类型的指针之间是没有什么算术运算

    • p++ 和 p-- 也算 p + n 操作

  • 指针的偏移和存储的数据类型有关,int 类型占用 4 个字节,+ 3 总共移动 12 个字节,char 类型占用 1 个字节,+ 3 总共移动 3 个字节

#include <stdio.h>
int main()
{int* p = NULL;           //所指向的数据类型:int  大人一步走4米char* pc = NULL;       //所指向的数据类型:char 小孩子一步走1米printf("%p\n", NULL);  //0000000000000000//做字节上的偏移-> 和它操作的数据类型有关p = p + 3;            //大人走了3步  总共走了: 12米   0xC //p+sizeof(int)*3 : 0 + 4*3pc = pc + 3;           //小孩子走3步  总共走了: 3米    0x3//p + sizeof(char) * 3 : 0 + 1*3//类似加法的运算-> 不需要带int类型//int a = 1;//a = a + 3;printf("%p\n", p);printf("%p\n", pc);//指针的偏移字节数 == p + sizeof(指针所指向的类型)*n//两个指针相加没有实际含义//int a = 0;//int b = 1;//int* pa = &a;//int* pb = &b;//int* pd= pa + pb;   //表达式必须包含整型return 0;
}/*输出*/0000000000000000
000000000000000C
0000000000000003

内存四区

在c语言中会把内存分成4个区域

学习内存四区可以帮助理解指针运算中的错误代码

静态变量的特性

void print()
{static int num = 1;        //定义一个静态变量 这个代码运行的时候只执行一次//静态变量不做初始化默认为0num++;printf("%d\n", num);
}
int main()
{print();                //第一次调用 num=2print();              //第一次调用 num=3 会记录程序上一次运行的结果//num = 3;                 //静态变量有作用域-> 和全局变量的区别 只能在子函数中使用 报错
}

一些运用指针的经典错误

指针处理字符串的特例

操作常量区的字符串,不能修改

* pchar 指向第一个内存,等效于常量区的 I,常量区的内存不能做修改

指针变量可以指向一段内存(字符串),指向这段内存的首地址

返回一个指针

可以返回一个值,但是不能返回一个值的地址,但是字符串只能返回首地址

char* returnPoint()
{//返回局部变量地址,不允许 static修饰没有问题-> 静态区会保存数据//函数调用完,栈区内存会被系统自动回收(清除所有的数据)char array[10] = "ILoveyou"; //%s 打印方式,从首地址开始,打印到'\0'结束char* p = &array[0];     // 1.指针变量指向第一个变量的地址 2.返回字符串的首地址//处理方案:把数据存到堆区,返回堆区这段内存的首地址 堆区内存不会被系统自动回收return p;
}
int main()
{int* p = NULL;             //0 存放在常量区-> 指针没有指向一个变量导致修改了常量中的东西//*p = 1234;          //不能修改0所在的内存 引发了未经处理的异常:写入访问权限冲突-> 由于访问了常量区的内容导致的//printf("%d", *p);  //------------------------------------------------------char* str = "ILoveyou";  //解析:把这段字符串的首地址赋值给指针变量-> 并没有把"ILoveyou"存到指针变量中去char* pchar;puts(str);pchar = "ILoveyou";//*pchar = 'M';           //写入访问权限冲突-> *pchar等效于'I' 'I'存在常量区不能修改puts(pchar);//-------------------------------------------------------char array[10] = "ILoveyou";pchar = &array[0];       //取第一个位置的地址-> 把I的地址赋值给 *pchar*pchar = 'M';            //把"ILoveyou"从常量区拷贝到栈区-> 修改栈区变量的内存puts(array);int* result = returnPoint();puts(result);puts(result);puts(result);puts(result);return 0;
}/*输出*/ILoveyou
ILoveyou
MLoveyou
頊槷?
頊槷?
頊槷?
頊槷?

万能指针

  • 万能指针就是void* 类型的指针变量

  • 能够操作任何类型的地址

  • 万能指针在访问数据的时候必须要做强制类型转换

#include <stdio.h>
int main()
{int num = 10;void* pVoid = &num;      //解析: pVoid=&num; 不是*pVoid=&num-> 定义变量时 *起说明作用 表示类型//printf("%d\n",*pVoid);   不能直接这样使用 必须要做强制类型转换为int*类型才能访问数据printf("%d\n", *(int*)pVoid);    double dNum = 1.11;pVoid = &dNum;printf("%.3lf\n", *(double*)pVoid);//万能指针使用的时候要强制转换为目标类型(指向数据类型的指针)int number = 0x00410042;  //字节的高低 左边:高位(高字节)  右边:低位(低字节)printf("%d\n", number);void* p = &number;char* pp = (char*)p;//一个十六进制位是4个二进制位//两位十六进制位是一个字节 4个字节用8个十六进制位表示//8个二进制位是一个字节    8个二进制位是2个十六进制数printf("%c\n", *pp);     //42 -->B  //0000005B9FDBF5E4  低地址char* pc = (char*)p;      //转换为char类型做偏移printf("%c\n", *(pc + 2));//41 -->A   //000005B9FDBF5E6   高地址//小端模式  高字节存放到内存地址高的地址上//大端模式  高字节存放到内存地址低的地址上//十进制:1235//1高位 5低位printf("%p\n", pp);         //0000005B9FDBF5E4            低地址printf("%p\n", pc + 2);     //0000005B9FDBF5E6            高地址//万能指针应用: 统一接口(统一函数传参-> 以万能指针充当函数参数 可以传任何类型的指针)//malloc(void* p,int arrayNum); return 0;
}/*输出*/10
1.110
4259906
B
A
0000005B9FDBF5E4
0000005B9FDBF5E6
E4<E6 E4是低地址 E6是高地址

c语言 --- 指针相关推荐

  1. c语言获取指针分配的字节数,c语言指针知识点总结(共6篇).docx

    c语言指针知识点总结(共6篇) C语言指针教学中的知识点分析与总结 摘要:分析指针的基本概念及指针在数组.函数.字符串.动态存储分配等方面的应用,提出指针教学过程中易混淆概念及注意事项,对初学者深入理 ...

  2. C语言指针数组与数组指针的区别

    C语言指针数组与数组指针的区别 首先,顾名思义 数组指针是一个指针,是指向一个数组的指针,如 int (a*)[5]:这就是一个指向含有5个元素的数组的指针 指针数组是一个数组,它包含的元素全是指针变 ...

  3. simple c语言,C语言——指针(simple).ppt

    C语言--指针(simple) 莆田学院计算机教研室 2003年5月 指 针 绍兴文理学院自动化教研室 2011年4月 本讲主要内容 指针概述 地址· 指针· 指针变量 指针变量作为函数参数 指针与数 ...

  4. c语言115写成16进制,C语言指针问题

    C语言指针问题 來源:互聯網  2009-04-01 16:01:29  評論 分類: 電腦/網絡 >> 程序設計 >> 其他編程語言 問題描述: int a=115,*p;p ...

  5. C语言指针总结大学霸IT达人

    C语言指针总结大学霸IT达人 C语言的指针是C语言区别其它语言的最主要的特定之一.有了指针,C语言就可以抛开所有束缚,直接对内存中的数据进行操作,这样,不单对数据的操作更加快捷,并且可以高效的利用空间 ...

  6. CPU 以字节为单位编址,而 C 语言指针以指向的数据类型长度作自增和自减。

    切记:CPU 以字节为单位编址,而 C 语言指针以指向的数据类型长度作自增和自减.

  7. c语言 指针函数 详解,[NOTE-C]C语言指针详解(一)

    C语言指针让一切想法变成可能,强转和指针可以看做一项呼风唤雨的利器,但是C语言中指针应用又需要格外的小心,其更灵活的利用内存,因为不当的应用可能引起各种异常,这篇文章就是让我们一起来认识C指针,更好的 ...

  8. c语言指针的相关运算,C语言指针的运算

    本文讨论使用指针进行的运算,最重要的运算是获取指针所引用的对象或函数.也可以比较指针,使用指针来遍历一个内存区域. 使用指针读取与修改对象 间接运算符 * 生成内存中的位置,该位置的地址存储在一个指针 ...

  9. C语言指针和二维数组

    二维数组在概念上是二维的,有行和列,但在内存中所有的数组元素都是连续排列的,它们之间没有"缝隙".以下面的二维数组 a 为例: int a[3][4] = { {0, 1, 2, ...

  10. c语言首尾指针相同 则,6.C语言指针练习题.doc

    6.C语言指针练习题.doc 一.知识点 1.? 掌握指针.地址.指针类型.空指针(NULL)等概念: 2.? 掌握指针变量的定义和初始化.指针的间接访问.指针的加减运算.指针变量比较运算和指针表达式 ...

最新文章

  1. Android中Broadcast
  2. 【深度学习理论】(1) 损失函数
  3. React 回忆录(三)使用 React 渲染界面
  4. IPv6 — 网际协议第 6 版
  5. 关于#!/bin/sh 和 #!/bin/bash 的差别
  6. MSSQL 从备份文件还原数据库脚本
  7. 【Linux】一步一步学Linux——ipcs命令(141)
  8. Java StringBuffer类
  9. CentOS 7.2.1511 x64下载地址
  10. wxpython wx listctrl_wxPython - ListCtrl列表排序
  11. Win10快查、关闭开机自启动软件 - 教程篇
  12. web.py框架入门
  13. C语言实现简单的单例模式
  14. 【动态规划】天上掉馅饼
  15. Element-UI + Vue.js + SpringBoot 实现前后端分离入门项目
  16. java 获取远程系统启动时间_从Java中的RuntimeMXBean获取系统启动时间
  17. C语言实现九九乘法表(四种情况)
  18. 51单片机间接寻址C语言,51单片机寄存器间接寻址方式与举例
  19. 杨玲 201771010133《面向对象程序设计(java)》第十三周学习总结
  20. java讲师助理面试题_面试Java开发师常问到的5个问题(附答案)

热门文章

  1. Spark面试,Spark面试题,Spark面试汇总
  2. java开发环境搭建小结
  3. 博客登录注册界面的实现
  4. 《数据统计分析及R语言编程(第二版)》练习题总结(一)
  5. 鸿蒙跨屏流转是什么,华为智慧屏SE系列评测:从用上到爱上 就是一“眼”之间...
  6. Apache-drill Architechture
  7. datagrip对Oracle支持不好,datagrip 连接oracle
  8. SecureCRT和SecureFX(一)下载、安装、注册
  9. iOS在Xib加载自定义Xib视图
  10. Your anti-virus program might be impacting 防火墙