【C++ 深入浅出】C++指针运算和指针安全总结

指针的运算

指针p可以加上或减去一个整数n,但指针的这种运算的意义和通常的数值的加减
运算的意义是不一样的,它是以单元为单位,如p指向int型整数,则一个单位是sizeof(int)

(1)示例1

char a[20]="You are my friend";
int *ptr=(int *)a;
ptr = ptr + 3; 

char数组的每个单位是一个字节,而指针ptr指向的单元是4个字节
所以没加3前的 ptr 指向数组a的第1 - 4个字节(看作一个整体),加3后,ptr已经指向了数组a的第13 - 16个字节,即指向a[12] - a[15]这部分

(2)示例2

#include <iostream>

using namespace std;

int main() {

    int array[20] = {0};
    int *ptr = array; // 数组名array是地址,把它赋给指针ptr

    for(int i = 0; i < 20; i++) {
        *ptr = i;
        ptr++;
    }

    ptr = array;
    for (int i = 0; i < 16; i += 4) {
        cout << *(ptr + 4) << endl;
        // 等价于cout << ptr[4] << endl; 
        ptr += 4; 
        // 因为ptr指向的是int,而数组array也是int
        // 所以指针ptr+4,等于下标i+4
    }
    return 0;
}

总结
一个指针(地址) ptrold 加(减)一个整数 n 后,结果是一个新的指针(地址) ptrnew
ptrnew 的类型和 ptrold 的类型相同,ptrnew 所指向的类型和 ptrold所指向的类型也相同

ptrnew 的值将比 ptrold 的值增加(减少)了 n 乘sizeof(ptrold 所指向的类型)个字节

也就是说:ptrnew 所指向的内存区将比 ptrold 所指向的内存区向高(低)地址方向移动了 n 乘sizeof(ptrold 所指向的类型)个字节。

指针和指针进行加减:

  • 两个指针不能相加,这是非法操作
    因为进行加法后,得到的结果指向一个不知所向的地方,而且没有意义。
  • 两个指针可以相减
    但必须类型相同,可用于求数组大小,当然要记得除以sizeof(type)

数组和指针的关系*(p + 4) 和 p[4]

数组名array本质是一个指针,所以

int array[]={0,1,2,3,4,5,6};
int *p = array; 

记住一点
*(p + 4) 和 p[4]是等价的

*(array + 4) 和 array[4]是等价的

array[0]等价于 p[0],因为p = array;
所以实际上,上面四个都是等价的

指针和结构的关系p->data; 和 (*p).data

struct node {
	int data;
	int time;
}node;

node Tu;
node *p = &Tu;

只要记住一点:(*p).data和p->data; 是等价的

指针的安全问题

(1)示例1

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

上面的代码存在严重的错误,因为第三行代码p += 1执行后,p指向了整型变量a相邻的高地址方向的一块储存区域,而我们居然用第四行代码往这块区域里写入数据,这非常危险,因为我们不知道它里面原来的内容是什么,万一是系统十分重要的数据呢

在数组int a[10]时类似地操作可行,那是因为我们已经申请了一个长度长度为10的连续空间,这部分空间是我们已知的且可随意写数据的

所以说,我们在使用指针时一定要非常清楚:这个指针究竟指向了哪里

(2)示例2

当我们使用指针的强制类型转换p1=(type *)p2 时,如果 sizeof(p2 的类型) 大于 sizeof(ptr1 的类型),那么在使用指针 p1 来访问 p2 所指向的存储区时是安全的。否则是会出现严重问题的

char t = 'a';
int *p;
p = (int *)&t;
*p = 520;

运行代码,可能不会报错,但这存在着安全隐患,因为p指向的是字符a以及和它相邻高地址方向的三个字节,而后面三个字节的内容我们并不知道是什么,万一很重要的呢

(3)下面的代码是安全的,而且可以说明我的机器是小端模式

因为从t最后的值为48,可以看出p指向的是int4个字节中的低字节,而强制转换的char指针p默认是指向int4个字节中低地址的字节的,所以可以说明我的机器是小端模式(低字节在低地址)

 int t = 7;
 char *p; 
 p = (char *)&t;
 *p = '0'; // 对应48:00110000  char 一个字节:0-127
 cout << *p << endl; 
 cout << t << endl; // 输出48
发布了239 篇原创文章 · 获赞 80 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/qq_43827595/article/details/104344130