当前位置: 首页 > news >正文

汽车网站网页模板制作视频网站教程

汽车网站网页模板,制作视频网站教程,百度指数怎么查询,网站优化软件目录 1. 指针的运算 2. 野指针和悬空指针 2.1 野指针 2.2 悬空指针 3. void类型指针 4. 二级指针和多级指针 4.1 命名规则 4.2 作用 4.2.1 二级指针可以操作一级指针记录的地址 4.2.2 利用二级指针获取变量中记录的数据 1. 指针的运算 文章开始前可以先了…

目录

1.  指针的运算

2.  野指针和悬空指针

2.1  野指针

2.2  悬空指针

3.  void类型指针

4.  二级指针和多级指针

4.1  命名规则

4.2  作用

4.2.1  二级指针可以操作一级指针记录的地址

4.2.2  利用二级指针获取变量中记录的数据


1.  指针的运算

文章开始前可以先了解:C语言指针·入门用法超详解-CSDN博客

        通过上一章我们初步了解了指针的用法,知道指针的类型是:

        其中指针中数据类型的作用是获取字节数据的个数,正常情况下变量p只能获取到0x001的内存地址,而int型数据占4字节,因此:

        那么我们可以思考一下,若是:

int a=10;
int* p=&a;p+1

        假设a的地址为:0x01,那么p+1指向的地址会是什么呢?

        会是0x02还是0x05呢?

        正确答案应该是:0x05,这是为什么呢?

步长:指针移动一次的字节个数

        因为,指针的加法操作实际上是将指针向后移动若干个存储单元,而不是简单的数学加法,上面我们也提到了正常情况下变量p只能获取到0x01的内存地址,而int型数据占4字节,而p+1就是指针移动一步,一步在这里是四个字节,因此p+1,最终会移动到0x05的位置。我们拿代码验证一下:

#include <stdio.h>int main()
{/** 指针的运算* 步长:指针移动一次,走了多少字节* char:1* short:2* int:4* long:4* long long:8*///加法:指针往后移动了N步P+N//减法:指针往前移动了N步P-Nint a = 10;int* p = &a;printf("%p\n", p);printf("%p\n", p + 1);printf("%p\n", p + 2);printf("%p\n", p - 1);printf("%p\n", p - 2);return 0;
}


注意:

指针有意义的操作:

        指针跟整数进行加、减操作(每次移动N个步长)

        指针跟指针进行减操作(间隔步长)

#include <stdio.h>int main()
{/** 有意义的操作:指针跟整数进行加、减操作(每次移动N个步长)指针跟指针进行减操作(间隔步长)无意义的操作:指针跟整数进行乘除操作原因:此时指针指向不明指针跟指针进行加、乘、除操作*///前提条件:保证内存空间是连续的//数组int arr[] = { 1,2,3,4,5,6,7,8,9 };//获取0索引的内存地址int* p1 = &arr[0];//指针跟整数进行加、减操作(每次移动N个步长)//通过内存地址获取数据printf("%d\n", *p1);printf("%d\n", *(p1 + 1));//获取5索引的内存地址int* p2 = &arr[5];//p2 - p1间隔了多少步长printf("%d\n", p2 - p1);printf("%p\n", p1);printf("%p\n", p2);return 0;
}

指针无意义的操作:

        指针跟整数进行乘除操作

        原因:此时指针指向不明

        指针跟指针进行加、乘、除操作


2.  野指针和悬空指针

2.1  野指针

        野指针:指针指向的空间未分配。

#include <stdio.h>int main()
{/*野指针:指针指向的空间未分配悬空指针:指针指向的空间已分配,但是被释放了*///野指针:指针指向的空间未分配int a = 10;int* p1 = &a;printf("%p\n", p1);printf("%d\n", *p1);//p2为野指针int* p2 = p1 + 10;printf("%p\n", p2);printf("%d\n", *p2);return 0;
}

        此时运行程序,虽然也能得到p2的地址,但是要知道,这块地址我们并没有给他分配,他虽然能找到地址,但是若是随意修改数据,在正常使用中,可能会修改别的函数的数据,导致最终运行错误: 

2.2  悬空指针

        悬空指针:指针指向的空间已分配,但是被释放了。

#include <stdio.h>int* method();int main()
{/*野指针:指针指向的空间未分配悬空指针:指针指向的空间已分配,但是被释放了*///悬空指针:指针指向的空间已分配,但是被释放了int* p3 = method();printf("拖点时间\n");printf("拖点时间\n");printf("拖点时间\n");printf("拖点时间\n");printf("拖点时间\n");printf("拖点时间\n");printf("%p\n", p3);printf("%d\n", *p3);return 0;
}int* method()
{int num = 10;int* p = &num;return p;
}

        会发现此时代码数据错误,正常p3应当显示10: 

        这里可以调用static来使用:

#include <stdio.h>int* method();int main()
{/*野指针:指针指向的空间未分配悬空指针:指针指向的空间已分配,但是被释放了*///悬空指针:指针指向的空间已分配,但是被释放了int* p3 = method();printf("拖点时间\n");printf("拖点时间\n");printf("拖点时间\n");printf("拖点时间\n");printf("拖点时间\n");printf("拖点时间\n");printf("%p\n", p3);printf("%d\n", *p3);return 0;
}int* method()
{static int num = 10;int* p = &num;return p;
}

3.  void类型指针

特殊类型:void* p

不表示任何类型,只能记录地址值,不能获取到变量里面的数据,也不能进行加减的计算。

特点:无法获取数据,无法计算,但是可以接收任意地址数据。

        在我们使用指针的过程中会发现,不同类型的指针之间是不能相互赋值的,否则会发生编辑错误:

#include <stdio.h>int main()
{//void类型指针//定义两个变量int a = 10;short b = 20;//定义两个指针int* p1 = &a;short* p2 = &b;//输出打印printf("%d\n", *p1);printf("%d\n", *p2);//不同类型的指针之间是不能相互赋值的char* p3 = p1;printf("%d\n", *p3);//这里编译器为我们进行了强制类型转换,上面的过程相当于如下char* p4 = (char*)p1;printf("%d\n", *p4);return 0;
}

         这里的指针间进行复制那是因为编译器在编译过程中,对p1进行了强制类型转换,p3的实际流程,如p4所示:

        为了解决这一问题我们可以将数据类型定义为void,不过这也会导致,不能printf输出数据,因为void不能获取到变量里面的数据,也不能进行加减的计算,否则编译器会报错:

#include <stdio.h>int main()
{//void类型指针//定义两个变量int a = 10;short b = 20;//定义两个指针int* p1 = &a;short* p2 = &b;//输出打印printf("%d\n", *p1);printf("%d\n", *p2);//不同类型的指针之间是不能相互赋值的char* p3 = p1;printf("%d\n", *p3);//这里编译器为我们进行了强制类型转换,上面的过程相当于如下char* p4 = (char*)p1;printf("%d\n", *p4);//void类型指针打破上面的观念//void没有任何类型,好处可以接收任意类型指针记录内存地址void* p5 = p1;void* p6 = p2;//缺点:不能获取到变量里面的数据,也不能进行加减的计算//printf("%d\n", *p5);//printf("%d\n", *p6);//printf("%d\n", *p5 - 1);//printf("%d\n", *p6 + 1);return 0;
}

        那么我们引用void有什么用呢?

        例如,我们用于调用函数进行交换数据,我们可以编写如下代码:

#include <stdio.h>void swap(void* p1, void* p2);int main()
{//void类型指针//定义两个变量int a = 10;short b = 20;//定义两个指针int* p1 = &a;short* p2 = &b;//输出打印printf("%d\n", *p1);printf("%d\n", *p2);//不同类型的指针之间是不能相互赋值的char* p3 = p1;printf("%d\n", *p3);//这里编译器为我们进行了强制类型转换,上面的过程相当于如下char* p4 = (char*)p1;printf("%d\n", *p4);//void类型指针打破上面的观念//void没有任何类型,好处可以接收任意类型指针记录内存地址void* p5 = p1;void* p6 = p2;//缺点:不能获取到变量里面的数据,也不能进行加减的计算//printf("%d\n", *p5);//printf("%d\n", *p6);//printf("%d\n", *p5 - 1);//printf("%d\n", *p6 + 1);//调用函数交换数据int c = 100;int d = 200;swap(&c, &d);printf("c=%d,d=%d\n", c, d);return 0;
}//函数:用来交换两个变量记录数据void swap(int* p1, int* p2)
{int temp = *p1;*p1 = *p2;*p2 = temp;
}

         此时可以实现数据的交换:

        但是若是此时我想使用long long型数据呢?数据会发生报错(我在DevC++上运行报错,在VS上运行正确,因为VS在这里编辑器给他自动强制类型转换了):

#include <stdio.h>void swap(void* p1, void* p2);int main()
{//void类型指针//定义两个变量int a = 10;short b = 20;//定义两个指针int* p1 = &a;short* p2 = &b;//输出打印printf("%d\n", *p1);printf("%d\n", *p2);//不同类型的指针之间是不能相互赋值的char* p3 = p1;printf("%d\n", *p3);//这里编译器为我们进行了强制类型转换,上面的过程相当于如下char* p4 = (char*)p1;printf("%d\n", *p4);//void类型指针打破上面的观念//void没有任何类型,好处可以接收任意类型指针记录内存地址void* p5 = p1;void* p6 = p2;//缺点:不能获取到变量里面的数据,也不能进行加减的计算//printf("%d\n", *p5);//printf("%d\n", *p6);//printf("%d\n", *p5 - 1);//printf("%d\n", *p6 + 1);//调用函数交换数据long long c = 100L;long long d = 200L;swap(&c, &d);printf("c=%lld,d=%lld\n", c, d);return 0;
}//函数:用来交换两个变量记录数据void swap(int* p1, int* p2)
{int temp = *p1;*p1 = *p2;*p2 = temp;
}

        那么我们如何才能进行不同类型都能调用该函数呢?可以使用void类型,

void swap(void* p1, void* p2)
{int temp = *p1;*p1 = *p2;*p2 = temp;
}

        但是如果使用void又会出现新的问题就是:void不能获取到变量里面的数据,也不能进行加减的计算,那么要如何解决呢?

           这里将void*类型的指针p1和p2分别转换为char*类型的指针pc1和pc2。这是因为char类型是 C 语言中的基本数据类型,且大小为1字节,所以可以通过char*指针逐字节访问内存。     

        同时函数void swap(void* p1, void* p2, int len)加上一个len用于表示字节数,要是int型len就等于4,long long就是等于8(在x64环境下):

void swap(void* p1, void* p2, int len)
{//把void类型的指针,转换char类型的指针char* pc1 = p1;char* pc2 = p2;char temp = 0;//以字节为单位,一个字节一个字节的进行转换for (int i = 0; i < len; i++){temp = *pc1;*pc1 = *pc2;*pc2 = temp;pc1++;pc2++;}
}

        完整程序代码: 

#include <stdio.h>void swap(void* p1, void* p2, int len);int main()
{//void类型指针//定义两个变量int a = 10;short b = 20;//定义两个指针int* p1 = &a;short* p2 = &b;//输出打印printf("%d\n", *p1);printf("%d\n", *p2);//不同类型的指针之间是不能相互赋值的char* p3 = p1;printf("%d\n", *p3);//这里编译器为我们进行了强制类型转换,上面的过程相当于如下char* p4 = (char*)p1;printf("%d\n", *p4);//void类型指针打破上面的观念//void没有任何类型,好处可以接收任意类型指针记录内存地址void* p5 = p1;void* p6 = p2;//缺点:不能获取到变量里面的数据,也不能进行加减的计算//printf("%d\n", *p5);//printf("%d\n", *p6);//printf("%d\n", *p5 - 1);//printf("%d\n", *p6 + 1);//调用函数交换数据int c = 100;int d = 200;swap(&c, &d, 4);printf("c=%d,d=%d\n", c, d);return 0;
}//函数:用来交换两个变量记录数据
/*
void swap(int* p1, int* p2)
{int temp = *p1;*p1 = *p2;*p2 = temp;
}
*///修改一下函数,更具有通用性
//因为以上函数,若是主函数调用的话,只能int类型的数据
void swap(void* p1, void* p2, int len)
{//把void类型的指针,转换char类型的指针char* pc1 = p1;char* pc2 = p2;char temp = 0;//以字节为单位,一个字节一个字节的进行转换for (int i = 0; i < len; i++){temp = *pc1;*pc1 = *pc2;*pc2 = temp;pc1++;pc2++;}
}

4.  二级指针和多级指针

4.1  命名规则

        以二级指针为例,上一章最初我们了解了什么是指针?

C语言指针·入门用法超详解-CSDN博客

         那么既然普通变量就有指针,指针也是一个变量为什么不能有一个指针继续指向他呢?那么我们可以了解到:

        既然指针也有他的指针,那么指针的指针要怎么命名呢?

        其和指针的命名规则是一样的也是:

数据类型  *  变量名;

        但是需要注意的是:指针的数据类型要跟指向空间中的数据的类型保持一致。

        首先对于指针p,其指向数据a的地址,需要和a数据类型保持一致,那么指针的命名就是:

int                       *                    p;

数据类型           标记            变量名

        然后,二级指针指向的是指针的数据类型,此时指针空间内存储的不是数据,而是a的地址,他的数据类型是int*,也就是说二级指针的命名:

int*                       *                    p;

数据类型           标记            变量名

4.2  作用

4.2.1  二级指针可以操作一级指针记录的地址

        上代码:

#include <stdio.h>int main()
{//定义变量int a = 10;int b = 20;//定义一级指针int* p = &a;printf("a的地址:%p\n", &a);printf("b的地址:%p\n", &b);printf("修改前p的地址:%p\n", p);//定义二级指针int** pp = &p;*pp = &b;printf("修改后p的地址:%p\n", p);return 0;
}

        可以发现p的地址被修改了,简单点来说:初始时,p指向变量a的地址。然后,通过pp这个二级指针,修改了p的指向,使其指向了变量b的地址。因此,最后输出显示p的地址发生了变化,从指向a的地址变为指向b的地址。

4.2.2  利用二级指针获取变量中记录的数据

#include <stdio.h>int main()
{//定义变量int a = 10;int b = 20;//定义一级指针int* p = &a;//定义二级指针int** pp = &p;printf("修改前获取变量里面的数据:%d\n", **pp);*pp = &b;printf("修改后获取变量里面的数据:%d\n", **pp);return 0;
}

C语言指针·入门用法超详解-CSDN博客

指针_时光の尘的博客-CSDN博客

http://www.yayakq.cn/news/750237/

相关文章:

  • wordpress主题 ftp网站seo优化教程
  • 做兼职做网站的是什么怎么制作网页内容
  • 庆阳做网站的公司wordpress define
  • 广州一流高校建设网站企业app下载安装
  • asp网站源码免费下载校园推广大使的职位描述
  • 家具营销型网站推广app的营销策略
  • 添加网站绑定主机名网站建设与推广是什么意思
  • 源码资源下载站小程序免费制作平台用
  • wordpress粒子特效郑州搜狗关键词优化顾问
  • 珠海做网站哪家最专业湖北建站方案
  • 网站建设技术标准wordpress 后台管理设置
  • 网站用免费空间好不好知名品牌营销策划案例
  • 凡科建站的优势台州网络推广
  • 网站建设开发详细步骤流程中元建设集团股份有限公司网站
  • 有关做美食的网站乐开个网址多少钱
  • 2017两学一做网站wordpress 邀请机制
  • 十堰哪家网站制作公司技术好做男装去哪个网站好
  • 东莞seo整站优化电影网站做静态是不是好一些
  • 网站上推广游戏怎么做的php做网站基本流程
  • 预付网站建设费用怎么做分录百度关键词推广价格查询
  • cms 企业网站管理系统erp系统的主要功能
  • 上海公司建立网站吗阿里云备案 网站备案域名
  • 网站怎么才能上线网站和微信
  • 代做毕设网站可信么大连高端网站建设
  • 威海设计网站的2012r2做网站
  • 网站建设的需求是什么意思表格在网站后台是居中可到前台为什么不居中
  • 如何看网站的浏览量在线登录qq网页版
  • 营销类网站有哪些wordpress 仿糗事百科
  • 小白测评做网站百度开户需要什么条件
  • 微网站app制作十大免费erp管理软件