你必须知道的指针基础-3.指针的移动及指针的危险

一、指针的移动

1.1 指针的向前及向后移动

  指针每次加一就是指针向前移动指针类型对应的字节数。下面通过一个int指针来指向一个int数组,看看指针的加法运算到底是个什么鬼?

    int nums[]={33,55,77,88,99};
    int* ptr = nums;
    printf("%d\n",*ptr);
    ptr++; // ptr是int类型的指针,所以向后移动4个字节
    printf("%d\n",*ptr);
    ptr+=2; // 向后移动2*4 个字节
    printf("%d\n",*ptr);

  运行结果如下图所示:

  可以看到,指针的加法就是向前移动指定类型字节数,在数组中就是指向下一个元素。

  下面再来看看与加法相反的减法,仍然以上面的代码为例,新增一句:ptr--;

    int nums[]={33,55,77,88,99};
    int* ptr = nums;
    printf("%d\n",*ptr);
    ptr++; // ptr是int类型的指针,所以向后移动4个字节
    printf("%d\n",*ptr);
    ptr+=2; // 向后移动2*4 个字节
    printf("%d\n",*ptr);
    ptr--;
    printf("%d\n",*ptr);

  运行结果如下图所示:

  可以看出,减法即代表向后移动指针类型对应的字节数

1.2 char类型指针的移动

  对于char类型的指针移动,实际就是指向下一个字符或上一个字符:

    char s1[]="hello edisonchou.cn";
    char* p=s1;
    p=p+2; // char类型占一个字节,因此这里向后移动2*1个字节
    printf("%s\n",s1);
    printf("%s\n",p);

  这里实现了一个类似于求子串的操作,运行结果如下图所示:

1.3 同类型指针的相减

  同类型指针相减,得出的是相距的数据类型的长度。下面以两个指向同一个int数组的int类型指针为例,验证一下是否得到相距的数据类型的长度:

    int nums[]={33,44,55,66,77};
    int* iP1=nums;
    int* iP2=nums;
    iP2=iP2+3; // 同类型指针相减得出的是相距的数据类型的长度
    printf("The distance is %d\n",iP2-iP1);

  当iP2-iP3得到的是距离是3,这是因为iP2在进行减法操作之前已经向前移动了3个int类型的长度。

二、指针强大但又危险

2.1 从你家到他家

  刚刚了解了指针的移动的强大,现在我们来看看指针的强大所带来的一些“危险”。例如下面一段代码,我们定义了两个int类型的整数。

    int i1=555;
    int i2=666;
    int* p=&i1;
    printf("%d,%d\n",&i1,&i2);
    p--;
    int i3=*p; //从p当前指向的内存中取出4个字节,解释成i3
    printf("%d\n",i3);

  在指针p的定义中,我们指向的是i1。而当我们对p指针进行减法运算移动时,我们发现当前p指针指向的居然不是i1而是i2了。这也就说明,本来声明指针时指向的是你家的地址,而当对指针进行运算操作后却指向了隔壁老王家的地址,这是搞什么鬼!

  可以从运行结果图看出,i1和i2的地址分别为2686740和2686736(是连续的地址),p指针最开始指向的是i1。而当p向后移动之后,此时已经指向了i2。因此,输出的值为666。

2.2 内存访问越界

  继续上面的例子,我们此时再将p指针向后移动,看看此时p指针所指向的内容的值是多少?当我们再把p指针向后移动99999位时,其所指向的内容的值又是多少?

    int i1=555;
    int i2=666;
    int* p=&i1;
    printf("%d,%d\n",&i1,&i2);
    p--;
    int i3=*p; //从p当前指向的内存中取出4个字节,解释成i3
    printf("%d\n",i3);

    p--;
    printf("%d\n",*p);

  当运行程序后,结果变为了下图:

  那么,这个4200782地址是个什么鬼?它存放的又是什么内容?我们不得而知,这也是另一个程序里边某个变量所存储的位置,但现在在我们这个程序中居然通过指针访问到了!这是个可怕的事情!想想,当A程序中的指针通过移动取得了B程序中的内存地址或数据内容,再对指针对其修改数据,这是一件不安全的事儿!想想一帮苦逼程序员辛辛苦苦加班加点做的游戏,轻而易举地就被挂了外挂,本来需要用RMB才能买的积分或者道具让外挂直接给改了,是不是觉得人生已经没有意义啦?

  下面一段代码则展示了,当指针移动的距离过大时,Windows系统会对此访问限制,程序直接报错。

    p-=99999; //这个内存地址可能是无法访问的,又被称为访问越界
    //Windows对此做了访问越界的限制
    printf("%d\n",*p);

  运行结果是,直接崩溃,弹出错误按钮:

  错误框的出现,代表了指针使用不当的危害,会给客户造成一定时间的延迟服务。因此,指针虽然很强大,但是也很危险!

参考资料

  如鹏网,《C语言也能干大事(第三版)》

作者:周旭龙

出处:http://edisonchou.cnblogs.com

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。

时间: 2024-10-26 08:56:47

你必须知道的指针基础-3.指针的移动及指针的危险的相关文章

C语言 指针基础篇 数组,函数与指针的运用 2 14

下面看看如何在函数中运用指针吧 下面是往函数传入指针的简单操作,不是传入数组的.判断一个a是否大于b是的话给,是的话对其进行操作,不是的话就直接返回. 1 #include <stdio.h> 2 int main(){ 3 int num1,num2,*p1,*p2; 4 p1 = &num1,p2=&num2; 5 scanf("%d%d",&num1,&num2); 6 7 int fun(int *n1,int *n2); //我们在

C语言--&gt;(十)指针基础

知识点: 1.指针基础 2.指针和函数(地址传递) ======================================= 指针是C中的一个重要的概念,也是C的一个重要特色.掌握指针的应用,可以使程序简洁.紧凑.高效. 指针的概念比较复杂,使用也比较灵活,因此初学时会常出错,我们要理解每一个概念的本质,多加练习,在实践中掌握它. 程序使用指针和没有没有使用指针的代码是两个档次. ========================================指针基础 [地址概念] 1.生

Boost智能指针-基础篇

简介 内存管理一直是 C++ 一个比较繁琐的问题,而智能指针却可以很好的解决这个问题,在初始化时就已经预定了删除,排解了后顾之忧.1998年修订的第一版C++标准只提供了一种智能指针:std::auto_ptr(现以废弃),它基本上就像是个普通的指针:通过地址来访问一个动态分配的对象.std::auto_ptr之所以被看作是智能指针,是因为它会在析构的时候调用delete操作符来自动释放所包含的对象.当然这要求在初始化的时候,传给它一个由new操作符返回的对象的地址.既然std::auto_pt

二级指针基础知识

/* ============================================================================ Name : TestDoublePointer.c Author : lf Version : Copyright : Your copyright notice Description : 二级指针基础知识 ================================================================

C语言05指针基础

1 局部变量和全局变量 1.1 问题 分别定义一个局部变量和全局变量,测试生命期限和作用域. 1.2 步骤 实现此案例需要按照如下步骤进行. 步骤一:局部变量和全局变量 代码如下所示: #include <stdio.h> /*auto*/ int x = 1000; void f1(int a) { a = 10; auto int x = 20; static int y = 30; y++; x++; printf("in f1(),a=%d,x=%d,y=%d\n"

C语言基础学习5:字符串与指针

1.字符串的表示形式 (1)用字符数组存放一个字符串,然后输出该字符串. char string[] = "I am happy"; printf("%s",string); (2)用字符指针指向一个字符串. char *string = "I am happy"; printf("%s",string); 2.字符指针作函数参数 (1)用字符数组作参数 void CopyString(char from[], char to

C++中的指针基础

C++ -- 指针 1.指针基础 指针是一个变量,其存储的是值的地址,并不是值本身.要获得一个变量的地址,要通过地址运算符&实现. eg: int a = 4; int *p = &a; 这里指针p就存储了a的内存地址,p指向变量a的地址.指针表示一个变量地址,要想通过指针获取值,需要*运算符,称为间接值或解除引用,将其应用于指针,可以获取该地址存储的值.如*p,*符号后面必须是指针. #include <iostream> using namespace std; int m

C语言基础学习3:数组与指针

数组元素的指针就是数组元素的地址. 1.指向数组元素的指针 C语言规定数组名(不包括形参数组名,形参数组并不占据实际的内存单元)代表数组中的首元素(即序列为0的元素)的地址. int a[10]; int *p1,*p2; p1 = &a[0]; p2 = a; p1和p2指向同一个数组a[10]. 2.通过指针引用数组元素 按C语言的规定,如果指针变量p已指向数组中的一个元素,则p+1指向同一个数组中的下一个元素,而不是将p的值(地址)简单的加1. 如果p的初值为&a[0],则 (1)

C-Xcode真随机数的产生, 指针基础, 小技巧

小技巧1: 输出一个 % 输出一个%号(因为%是格式控制符的符号,所以输出是单独写一个%,系统会默认把%与其后面一个字符相结合当做格式控制符) —— %% 小技巧2: 自动整理代码 整理代码组合键 选中要对齐的代码 control + i 就会自动对齐 前提:代码没有语法错误 小技巧3: 产生一个真随机数 产生一个指定范围内的随机数: 比如需求:产生10-20的随机数 int num = arc4random_uniform(11) + 10 其他类推可得 公式 int num = arc4ra

C语言指针基础

C语言指针 前导程序   1 #include<stdio.h> 2 3 4 5 void change(int *); 6 7 int main() 8 9 { 10 11 int a=90; 12 13 change(&a); 14 15 printf("a=%d\n",a); 16 17 return 0; 18 19 } 20 21 22 23 void change(int *n) 24 25 { 26 27 *n=10; 28 29 } 30 31 一.