目录:
1. 指针是什么 
2. 指针和指针类型 
3. 野指针 
4. 指针运算 
5. 指针和数组 
6. 二级指针 
7. 指针数组

1.指针是什么:
1. 指针是内存中一个最小单元的编号,也就是地址 。
2. 平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量。
总结:指针就是地址,口语中说的指针通常指的是指针变量。
内存被划分为一个个小的内存单元。
一个基本的内存单元的大小时一个字节。
内存单元的编号-->地址。
          内存
地址(内存单元的编号)
一个字节
0✖FFFFFFFE
...
...
一个字节
0✖00000000
内存单元的编号是如何产生的呢?

机器分为30位或64位:                      (电信号转换为数字信号)
32位 - 32跟地址线 - 物理电线 - 通电 - 高电频/低电频 - 1/0
64位......
电信号产生的数字信号二进制序列作为内存单元的编号-->内存单元的地址:
00000000000000000000000000000000
00000000000000000000000000000001
......
11111111111111111111111111111111
共有2^32个地址,每个地址标一个字节,可以给4G的空闲内存编址(32位下)(2^32Byte == 2^32/1024KB == 2^32/1024/1024MB==2^32/1024/1024/1024GB == 4GB)。
所以:
内存单元 -- 编号 -- 地址 -- 指针
补充:
4个二进制位表示一个十进制位
比如:10
二进制:00000000 00000000 00000000 00001010
十进制:00 00 00 0a
指针变量:是用来存放地址的变量(存放在指针中的值都被当成地址处理)。
int a = 10;
int *pa = &a;
//pa是指针变量,pa的类型是int*
//pa中存放的是a的地址

解析:
(指针变量是一个变量,里面存放的是a的地址)
因为a是int型,所以&a拿到的是a的4个字节中的第一个字节的地址(每个字节都有自己对应的地址)
对int *的理解:
pa的类型是int*,对于int*可分开理解,*告诉我们pa是个指针变量,而前面的int告诉我们pa指向的变量a的类型是int(pa指向一个整型变量)。
前面说到一个地址占32bit=4byte,所以一个指针变量pa占4个字节。

因为一个地址占4个字节,要存起来这个地址,需要一个4字节的内存空间。(32位下,64位需要8个字节)
总结:
指针是用来存放地址的,地址是唯一标示一块地址空间的。 
指针的大小在32位平台是4个字节,在64位平台是8个字节。

2.指针和指针类型
指针类型的大小都是一样的,都占4个字节(double*、int*、short*......)
那么指针类型的意义是什么呢?
int a = 0x11223344;
int *pa=&a;
*pa = 0;
//得出的结果是让a中的4个字节存的数都变为0;
//11 22 33 44-->00 00 00 00

但是,当为:
int a = 0x11223344;
char *pa = &a;
*pa = 0;
//得出的是让a中的4个字节中的1个字节内存的数变为0;
//11 22 33 44-->11 22 33 00

总结:
1.指针类型的意义:
指针的解引用:
指针类型决定了在解引用的时候一次能访问几个字节(指针的权限)
int* --> 4
char* --> 1
couble* --> 8
2.指针类型决定了指针向前走一步或向后走一步,走多大距离(单位字节)
int a = 10;
int *pa = &a;
char *pc = &a;
printf("%p\n",pa);
printf("%p\n",pa+1);//打印的地址+1跳过4个字节(int型)
printf("%p\n",pc);
printf("%p\n",pc+1);//打印的地址+1跳过1个字节(char型)

强制转换:
int arr[10]={0};
char* p=(char*)arr;
return 0;

强制类型转换后大小并没有变,还是4个字节,只是一次访问由4字节改为1字节。

3.野指针
野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)

野指针的成因:
1.指针未初始化
int *p;//局部变量未初始化,是随机值
*p = 20;

补充:全局变量未初始化默认为0,局部变量未初始化为随机值。
2.指针越界访问
int arr[10] = { 0 };
int *p = arr;
int i = 0;
for(i = 0;i <= 10;i ++)
{
*p = i;
p ++;
}

arr
   0
   1
   2
...
   9
数组下标
0
1
2
...
9
10
当i=10的时候,*p=10,但是数组中一共只有0~9这10位,i=10时多出一位,这一位就造成数组越界,会出现野指针。

3. 指针指向的空间释放
int* test()
{
int a=100;
return *a;
}
int main()
{
int *p=test();
printf("%d",*p);
return 0;
}

函数运行时开辟内存存放100,有一个对应的地址,返回的时候返回的就是当时存放100的那个内存地址,p指向的就是当时存放a的地址,但是a有生命周期,函数调用完出去的时候,a就销毁了(不是说这块孔家不在了,而是这一块内存空间的使用权限不再属于test函数了),但是p里面还是存了这一块空间的地址,p就成为了一个野指针。(如果这个空间里存的东西没改过,去访问的时候里面还是a的值,但是如果被用过了,就不是a的值了。)
4.如何规避野指针
1. 指针初始化 
(当p不知道指向谁的时候就给它附一个空指针 int *p = NULL ;)
2. 小心指针越界 
3. 指针指向空间释放即使置NULL 
4. 避免返回局部变量的地址 
5. 指针使用之前检查有效
if(pa != NUULL)
{
}
//检查指针pa的有效性,当pa不等于空指针的时候再去使用它


4.指针运算
4.1指针+-运算
指针+-整数i跳过i个相应的类型个数。
for(i=0;i<sz;i++)
{
printf("%d",*(p+i));
}
//sz为数组中元素的个数
//用指针依次打印数组中的元素个数
int *p = arr + sz - 1;//p指向arr的最后一个元素
for(i=0;i<sz;i++)
{
printf("%d",*p--);
}
//反向打印数组中的元素

4.2指针-指针
int main()
{
int a[10]={0};
printf("%d\n",&a[9]-&a[0]);
printf("%d\n",&a[9]-&a[0]);
return 0;
}

输出结果为
9
-9
解析:
a
0
0
...
0
0
0
下标
0
1
...
7
8
9
地址由低到高排列,当两个地址相减的绝对值,得到的是两个地址之间元素的个数(不是字节个数)
(大地址-小地址--正数;小地址-大地址--负数)

注:指针-指针的前提是:两个指针指向同一块空间。
补充:
实现my_strlen的三种方法:
1.计数器
2.递归
3.指针-指针
这次展开讲指针-指针的方法
int my_strlen(char *s)
{
char *strart = s;//strart指向首元素
while(*s !='\0')
{
s++;
}
return s-start;//指针的减法,课算出两地址之间元素个数
}

4.3指针的关系运算
#define N_VALUES 5 
float values[N_VALUES]; 
float *vp;
for(vp = &values[N_VALUES]; vp > &values[0];) 
{    
*--vp = 0; 
}
//把数组中的元素都赋值为0;

values:                                               vp⬇(通过for循环中--向左赋值)
0
0
0
0
0
下标
0
1
2
3
4
5

这里for中的vp指针并未越界,只是指向数组外下标为5的空间,并没有访问这个空间。(vp中只是存了上图中下标为5的地址)

上面的代码可以进行简化:
for(vp = &values[N_VALUES-1]; vp >= &values[0];vp--) 
{    
*vp = 0; 
}

注意:
标准规定:
允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一个元素之前的那个内存位置的指针进行比较。

5.指针和数组
指针——地址(4字节/8字节)
数组——一组相同类型的数据(多大自己创建)
数组和指针是两种概念
我们可以通过指针访问数组。

6.二级指针
int main()
{
int a = 10;
int *pa = &a;
//pa中存放a的地址,占用4字节,而pa本身也有自己的地址
int **ppa = &pa;
//ppa就是二级指针,指向pa,ppa也有自己的地址
int ***pppa = &ppa;
//pppa是三级指针

对二级指针中*的理解:
int *pa=&a;  中 * 表示pa是一个指针,由于a的类型是int,pa指向的对象是int型,所以用int。
int **ppa=&pa;  中  **中的第二个*表示ppa是指针变量,第一个*和int组成int*,由于pa的类型是int*,ppa指向pa,所以这里是int*。
(指针指向谁,定义的时候就写什么类型,指向int就写int,指向int*就写int*)
*ppa找到的是pa,所以**ppa找到的就是a,可以通过**ppa修改a的值
**ppa=20;//把a中的值改为20
(*ppa=pa,**ppa=*pa=a)
总结:
二级指针是用来存放一级指针变量的地址的。

7.指针数组
指针数组是数组——存放指针的数组
int a = 10;
int b = 20;
int c = 30;
int *arr[5] = { &a , &b , &c };//存放整型指针的数组

arr中存放的都是int*型。
上面arr中不完全初始化,未定义的初始化为0,是空指针。
*(arr[0]) = a;

从零开始学C语言 : 初阶指针相关推荐

  1. 五十分钟带你看遍C语言初阶语法(总纲)

    C语言初阶语法(总纲) 此篇博客包含了前面C语言所有的基础语法,写这一期的博客不仅是为了记录自己的学习成果也是为了让更多的朋友能学到对自己有用的知识,如果总有一个知识点帮助到了你,给卑微博主点点关注加 ...

  2. c语言打印%-6llu,从零开始学C语言

    从零开始学C语言 @阆苑祁寒 写在前面:本文从一个初学者的角度,给出了对C语言的简单理解.如有谬误,敬请指出! Week1 1 #include 2 int main(void)3 {4 printf ...

  3. C语言初阶(18) | 数组详解

    目录 1.数组的定义 2.一维数组 2.1一维数组的格式 2.2一维数组的初始化 2.3一维数组的使用 2.4一维数组再内存中的存储 3.二维数组 3.1二维数组的创建和初始化 3.2二维数组的使用 ...

  4. C语言初阶_初识C语言(1)

    凡是过往,皆为序章 期末考试结束了,真是感慨良多啊...... C语言编程题大家都做对了多少呢? 不管怎么样,都已经过去了.不管你学得怎么样,都可以在接下来的时间里,我们一起重新回顾一遍C语言初阶的知 ...

  5. C语言初阶——5.字符串

    C语言初阶--5.字符串 1. 字符串操作 1.1 字符串遍历 可以通过数组方式遍历字符串. char* str="Hello World"; for(int i = 0;'\0' ...

  6. C语言初阶总结 v1

    目录 C 基础1⭐ 数据类型 计算机中的单位 常量与变量 字符串/转意字符/ 注释 C 基础2⭐ 判断语句 函数与数组 C语言操作符 C语言关键字 C语言定义宏与关键字 初始指针 ⭐⭐ 指针基础 拓展 ...

  7. 初阶指针---从入门到入坟

    今天我们来见识一下c语言里让万千少年少女从入门到入坟的一道大门槛--指针 目录 1.指针是什么? 2.指针和指针类型 3.野指针 4. 指针运算 5. 指针和数组 6. 二级指针 7. 指针数组 1. ...

  8. r语言中矩阵QR分解_从零开始学R语言Day4|向量、矩阵和数组

    从零开始学R语言Day4|向量.矩阵和数组 1.1向量 1.1.1向量 在Day2中我们提及过用和c()函数来构建向量,具体实例如下. 我们还可以采用vector("类型",长度) ...

  9. C语言初阶——6.进制

    C语言初阶--6.进制 1. 进制 百度百科: 进制也就是进位计数制,是人为定义的带进位的计数方法,对于任何一种进制-X进制,就表示每一位置上的数运算时都是逢X进一位. 十进制是逢十进一,十六进制是逢 ...

最新文章

  1. 2019.07.16
  2. ztree 默认选中节点_用户管理、角色管理、模块管理、zTree的使用
  3. named 客户端无法解析_Outlook邮件附件无法直接打开?用这个办法轻松解决
  4. [云炬创业学笔记]第二章决定成为创业者测试9
  5. OpenLayers3基础教程——OL3之Popup
  6. Flask框架-蓝图系统
  7. Teams新功能更新【六月底】Microsoft Teams: Music on Hold
  8. parallels网络初始化失败_33 个神经网络「炼丹」技巧
  9. windows下创建vp9的VS版本
  10. STC官方软件波特率计算器使用方法
  11. 数据优化 | CnOpenData中国工业企业绿色专利及引用被引用数据
  12. 【异常】java.lang.NoClassDefFoundError: com/lowagie/text/pdf/PdfContentByte
  13. GCC编译器原理(一)------GCC 工具:addr2line、ar、as、c++filt和elfedit
  14. Resnet18卷积神经网络实现图片分类算法(代码全注释)
  15. iPhone模拟器消失 解决办法
  16. SWAN测试用例botan/net2net-ed25519
  17. [Spring Boot]12 ElasticSearch实现分词搜索功能
  18. Android P 按键音分析
  19. 多张图带你彻底搞懂DNS域名解析过程
  20. vue 图片宫格_vue实现移动端九宫格布局

热门文章

  1. 60-网络分层的真实含义是什么?
  2. WIN10电脑桌面整理及其壁纸应用推荐
  3. 【算法】求解幂集问题
  4. MySql各版本介绍
  5. python爬虫疫情可视化
  6. NVIDIA Control Panel 出现问题。请与你的系统管理员联系,以了解有关修复或重新安装该应用的信息。 关于win10安装新版N卡驱动没有显卡控制面板的解决办法
  7. CCF-CSP认证 历届第一题
  8. 推荐一款高颜值第三方网易云客户端: YesPlayMusic
  9. 计算机类毕业设计优秀最新题目
  10. 有一个函数 x , x大于1 ,y等于 { 2x-1 1大于等于x小于10 3x-11 x大于等于10 写一段程序,输入x,输出y。