指针引入
指针:
一、声明 一个 int 类型的 指针 然后 赋值。
二、声明中直接赋值。
三、空指针
四、悬空指针 野指针:
悬空指针本质上就是 声明了一个 指针类型的变量【如:int *p】,并且没有赋值。在没有赋初值的情况下,利用这个指针进行修改【如:*p=100】。就相当于这个指针指向了一个未知的地址。并且还做了修改。那如果这个地址是其他进程。还做了修改,就会造成系统的不稳定。因为这种不可靠的修改行为极其可怕,就好像吕伯奢开放了自己家给曹操,曹操进来以后胡乱的修改吕伯奢家人的数据,把是否存活全都置成了false.在dos版本的操作系统下,这种修改行为还是可以的。但是随着后来越来越多的黑客想要修改操作系统的数据,就相当于我操作系统很大度,开放了我自己给你,你运行了一些东西,让我这个操作系统土崩瓦解了。所以后来的操作系统做成了如下图的样子:
也就是随着后来越来越多的这种可怕行径,导致后来的法律发现如果你越界访问的话,我们就认定你是非法入室罪名。就是有一个进程不断地检测,如果 有用户进程非法访问,就立刻把这个进程从内存中清楚,以保护操作系统的稳定。所以我们现在 是可以放心做这种悬空指针的案例演示的,不过就是 我们的进程遇到了问题,被迫中止而已。这是可以接受的。
五、指针的兼容问题
以下代码:
#include <iostream> void function1(void); void function2(void); void function3(void); void function4(void); void function5(void); int main() { function5(); return 0; } /** 声明 一个 int 类型的 指针 然后 赋值。 */ void function1(void){ int i= 10; printf("修改前i的值为:%d\n",i); int *p;//定义一个 执行int 类型的指针 变量名为p. p = &i;//取i的地址 赋给 p。 *p = 100;//*p表示:访问p中的内容,根据int 这个类型,来提取这个元素。 //又因为刚刚给这个里面赋了i这个值 ,所以*p 相当于i。那么i=100. //所以 *p = 100 本质上是一个赋值语句,将i的值改成了100. printf("修改后i的值为:%d\n",i); } /** 声明中直接赋值。 */ void function2(void){ int i =10; int *p = &i; printf("i的值为:%d\n",*p); } /** 空指针 */ void function3(void){ //int b = NULL; //printf("b的值为:%d\n",b); int *p = NULL;//这就是传说中的空指针,在java中报了错比较常见这个东西的, //就是因为在创建对象的时候,没有给定一个初值,导致 报了那样一个异常 printf("指针p的值为:%d,%p,%x",p,p,p); } /** 悬空指针,野指针 :其实 跟function1()的内容有相像的地方,就是声明一个指针类型的变量,但是不赋值。 这个 编译是可以通过的,但是运行的时候会报错。在visual studio c++ 里面编译通不过。 这是因为。谁也不知道 到底让p指向了一个什么样的内存单元。并且在不知情的情况下还给 它赋了100这个值, 那这样就会极其不安全。 */ void function4(void){ int *p; *p = 100; printf("悬空指针指向的地址的值是:%d\n",*p); } /** 指针的兼容问题 */ void function5(void){ //前面在第一个案例的时候有特意提到声明了一个 int类型的指针变量,是因为除此之外还有各种类型的指针变量。 //比如: char *pc; int array[10]; int *p =array;//这个我现在有点儿蒙。。。 double *pd; //也就是我们说的,先去找到那个对应的元素然后按照 char 类型取pc里面的内容 //按照double类型,取pd里面的值 //所以对于指针来说 他们的大小都一样: printf("指针变量pc的大小:%d\n指针变量p的大小%d\n指针变量pd的大小%d\n",sizeof(pc),sizeof(p),sizeof(pd)); //【查看运行结果图】,会发现在这台机器里面,所有的指针变量都是8,说明这是一个64位的操作系统。 //如果这些数值都是4说明这是一个32位的操作系统。所以指针变量这个值的大小是操作系统相关的。 //所以,在取值的时候需要为这个被指向的对象指明一个类型,方便在取的时候,按照合理的类型把这个元素提取出来。 // 为了继续进行先把这里注释掉,这里很关键!一定要动手尝试 //所以 如果是 int *p1; char c; //p1=&c; //就会报一个这样的错误: cannot convert 'char*' to 'int*' in assignment int *p2; unsigned int i1; //p1=&i1; //这个编译还是很严格的,就是不行。在vs里面这是被允许的。 //[Error] invalid conversion from 'unsigned int*' to 'int*' [-fpermissive] //但是 如果声明一个 指向空类型的 指针 在进行指向是被允许的。 void *pv; pv=&c; pv=&i1; //这样就是编译通过的。 //p1 = pv; //[Error] invalid conversion from 'unsigned int*' to 'int*' [-fpermissive] }
上面是 main.cpp 的情况
下面是 main.c的情况:
#include <iostream> int main() { int *p; unsigned int i; //p=&i; //[Error] invalid conversion from 'unsigned int*' to 'int*' [-fpermissive] int ii; p=ⅈ void *p1; p1 = p; char *pc; //pc = p1; //[Error] invalid conversion from 'void*' to 'char*' [-fpermissive] return 0; }