想美团这样的网站怎么做,无极县城内招聘临时工,中国建设银行招聘网站通知,百度top排行榜#x1f3af;每日努力一点点#xff0c;技术进步看得见 #x1f3e0;专栏介绍#xff1a;【C语言步行梯】专栏用于介绍C语言相关内容#xff0c;每篇文章将通过图片代码片段网络相关题目的方式编写#xff0c;欢迎订阅~~ 文章目录 什么是指针#xff1f;指针的大小指针类… 每日努力一点点技术进步看得见 专栏介绍【C语言步行梯】专栏用于介绍C语言相关内容每篇文章将通过图片代码片段网络相关题目的方式编写欢迎订阅~~ 文章目录 什么是指针指针的大小指针类型野指针指针运算指针和数组二级指针指针数组 什么是指针
在我们的日常生活中酒店为了方便找到某个房间会给每个房间都进行编号。
计算机中一个4GB的内存包含的字节数多如牛毛为了方便查找到每个字节所在的位置。我们就需要给内存的每个位置编个号这个编号就称为内存地址。 为了保存这个编号我们就需要使用一个变量来存储它也就是指针变量。这里要注意的是指针内存地址编号。而我们日常说的定义一个“指针”这里的指针指的是指针变量这里的“指针”并不是内存地址的意思。
在计算机科学中指针是编程语言中的一个对象利用地址它的值直接指向存在电脑存储器中另一个地方的值。由于通过地址能找到所需的变量单元可以说地址指向该变量单元。因此将地址形象化的称为“指针”。意思是通过它能找到以它为地址的内存单元。
例如我们定义指针变量p它存储值是0x00000001。这时使用p就能找到0x00000001这个内存单元。 指针变量用于存放内存单元的地址编号存放在指针变量中的值都被当成地址处理。下面来看一下如何定义一个指针变量↓↓↓
#include stdio.h
int main()
{int a 10;//在内存中开辟空间int* p a;//在内存中开辟一个指针变量p用它保存a的地址。return 0;
}指针的大小
我们的计算机分为32位机器和64位机器。32位机器表示它有32根地址线每个地址线可以产生0或者1在为内存编制地址时使用了32个比特位可以表示0到 2 32 − 1 2^{32}-1 232−1的地址。同理64位机器表示它有64根地址线在为内存编制地址时使用了64个比特位可以表示从0到 2 64 − 1 2^{64}-1 264−1的地址。
每8个比特位是一个字节。在32位的机器上地址是32个0或者1组成二进制序列那地址就得用4个字节32÷84的空间来存储所以一个指针变量的大小就应该是4个字节。那如果在64位机器上如果有64个地址线64÷88那一个指针变量的大小是8个字节才能存放一个地址。
总结 指针是用来存放地址的地址是唯一标示一块地址空间的。 指针的大小在32位平台是4个字节在64位平台是8个字节。
指针类型
变量有不同的类型整形浮点型等。那指针有没有类型呢 准确的说有的。
指针的定义方式是 type_name * 。 其实 char* 类型的指针是为了存放 char 类型变 量的地址。 short* 类型的指针是为了存放 short 类型变量的地址。 int* 类型的指针是为了存放 int 类型变量的地址。
#include stdio.h
int main()
{int a 10;int* pa a;short b 20;short* pb b;char c a;char* pc c;return 0;
}那指针类型的意义是什么
#include stdio.h
int main()
{int a 10;int* pa a;printf(%p\n, pa);printf(%p\n, pa 1);char c c;char* pc c;printf(%p\n, pc);printf(%p\n, pc 1);
}我们知道int类型占4个字节char类型占1个字节。对于int类型的指针变量如果1后存储的地址将向后移动4个字节对于char类型的指针变量如果1后存储的地址将向后移动1个字节。
所以指针的类型决定了指针向前或者向后走一步有多大距离。
指针变量保存了某个变量的地址那么怎么使用指针变量间接访问指针变量所指向的变量呢那就需要使用解引用操作符*星号。在指针变量的前面加上解引用操作符就能访问指针变量所指向的变量。↓↓↓
#include stdio.hint main()
{int a 10;int* pa a;printf(a %d\n, *pa);*pa 66;printf(a %d\n, a);//a的值被pa间接修改
}对于解引用操作符来说它是根据指针变量的类型来确定一次性需要读取操作多少个字节的空间。对于char类型解引用后需要操作1字节的空间对于int类型解引用后需要操作4字节的空间。
总结 指针的类型决定了对指针解引用的时候有多大的权限能操作几个字节。
野指针
野指针的概念 野指针就是指针指向的位置是不可知的随机的、不正确的、没有明确限制的。
野指针的几种情况
指针变量未初始化
#include stdio.h
int main()
{int* p;printf(%d\n, *p);return 0;
}★ps指针变量没有初始化时指针变量中保存的地址是不确定的。这时对该指针变量执行解引用操作可能引起程序崩溃。因为指针变量中的随机地址可能是其他程序所占有的地址还有可能是其他情况。等同于不是我的东西我没有权力操作
指针越界访问
#include stdio.h
int main()
{int arr[10] {1,2,3,4,5,6,7,8,9,10};int* p arr;for(int i 0; i 100; i){printf(%d\n, *p);p;}return 0;
}p一开始指向数组的首地址解引用后可以访问到第一个元素1p后会向后跳转4个字节也就是指向第二个元素的地址…一直执行操作直到p指向arr范围以外的地址时由于后序地址不知道属于谁随便访问并不安全甚至会导致程序崩溃。
3.指针指向的空间已经被释放
#include stdio.h
#include stdlib.h
int main()
{int* p (int*)malloc(sizeof(int));//申请了一个int类型的空间free(p);//释放一个int类型的空间*p 0;//errorreturn 0;
}在释放了空间后操作系统可能会将它分配给其他程序此时访问并修改它可能导致程序崩溃。
那如何规避野指针呢
指针初始化
#include stdio.h
int main()
{int* p NULL;//指针初始化int a;p a;return 0;
}小心指针越界指针指向空间释放即使置NULL
#include stdio.h
#include stdlib.h
int main()
{int* p (int*)malloc(sizeof(int));//申请空间free(p);//释放空间p NULL;//置为NULL
}指针使用之前检查有效性
#include stdio.h
int main()
{int* p (int*)malloc(sizeof(int));//申请空间有可能失败if(p NULL){printf(申请失败\n);}else{printf(申请成功可以使用\n);*p 100;printf(%d\n, *p);}return 0;
}指针运算
指针-整数 例如对于整型指针p对它4。由于整型占4个字节的空间对p4则p向后移动4个整型空间即16字节。
#include stdio.h
int main()
{int arr[10] {1,2,3,4,5,6,7,8,9,10};int* p arr;printf(%p\n, p);printf(%p\n, p 4);return 0;
}例如对于字符指针c对它4。由于字符型占1个字节的空间对c4则c向后移动4个字符型空间即4字节。
#include stdio.h
int main()
{char arr[] {a, b, c, d, e, f};int* c arr;printf(%p\n, c);printf(%p\n, c 4);return 0;
}指针-指针 一个指针变量减另一个指针变量可以计算出两个指针变量之间的元素个数。
#include stdio.h
int main()
{int arr[5] {1,2,3,4,5};int* p arr;int* t arr[4];printf(%d\n, t - p);//结果是4return 0;
}指针的关系运算 指针变量的比较就是地址进行大小比较。下面代码中定义了一个包含5个元素的数组数组是从低地址向高地址存储的。因此使用下标为0的元素的地址与下标为4的元素的地址进行比较时p1必然小于p2故下面代码执行结果为I am Jammingpro。
#include stdio.h
int main()
{int arr[5] {1,2,3,4,5};//数组元素从小地址向大地址存储int* p1 arr[0];int* p2 arr[4];if(p1 p2){printf(I am Jammingpro\n);}return 0;
}★ps允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较但是不允许与指向第一个元素之前的那个内存位置的指针进行比较。
指针和数组
数组名是什么它是不是和指针有什么关系呢我们来看一段代码↓↓↓
#include stdio.h
int main()
{int arr[3] {1,2,3};printf(arr %p\n, arr);printf(arr[0] %p\n, arr[0]);return 0;
}由上面代码的执行结果可以知道数组名就是数组首元素的地址。我们可以将数组名理解成指向首元素的指针但两者还是有区别的例如sizeof(arr)的大小是整个数组大大小而不是指针的大小说明指针和数组名不等划等号。
我们可以使用数组名数组下标通过对它解引用就可以访问数组第i号下标的元素。
#include stdio.h
int main()
{int arr[3] {1,2,3};int* p arr;//存储数组首元素的地址for(int i 0; i 3; i){printf(arr[%d] %d, *(p %d) %d\n, i, arr[i], i, *(p i));printf(arr[%d] %d, (p %d) %d\n, i, arr[i], i, (p i));}return 0;
}★ps这也就说明了为什么数组是从下标0开始的。因为arr[i]的本质就是*(arri)。
二级指针
上面我们讨论都是用一个指针变量保存一个变量的地址。如果我们用指针变量pc指向字符变量c再使用指针变量ppc指向指针变量pc的地址。像这种使用一个指针变量保存另一个指针变量的地址的情形称为二级指针。
#include stdio.h
int main()
{char c 0;char* pc c;char** ppc pc;printf(c %c\n, c);printf(*pc %c\n, *pc);printf(**ppc %c\n, **ppc);return 0;
}上面我们介绍了解引用的操作对于pc指针来说对它进行解引用后就可以操作字符变量c。对于ppc指针两说对它进行一次解引用操作后就可以操作pc指针如果对它进行两次解引用操作就可以操作字符变量c。
指针数组
听到这个名字让人有点疑惑。指针数组到底是指针还是数组其实指针数组就是一个用来保存指针的数组。
假设我们需要用一个数组保存3个整型数组由于数组的地址是int*类型的我们可以定义一个int* arr[3]来存储这3个整型数组的地址。 下面演示如何使用该arr指针数组访问其保存的各个数组的元素。↓↓↓
#include stdio.h
int main()
{int* arr[3] {0};int numArr1[5] {1,2,3,4,5,6};int numArr2[5] {1,2,3,4,5,6};int numArr3[5] {1,2,3,4,5,6};arr[0] numArr1;arr[1] numArr2;arr[2] numArr3;for(int i 0; i 3; i){for(int j 0; j 5; j){printf(%d , *((*arr[i]) j));}printf(\n);}return 0;
}★ps*arr[i]获取的是第i个数组的地址*((*arr[i]) j)获取的是第i个数组第j个元素。 这篇文章结束了~~ 如果文章中出现了错误欢迎私信或留言。(๑•̀ㅂ•́)و✧ 有任何疑问请评论或私信哦~~o(▽)ブ