设为首页 加入收藏

TOP

C++入门教程之指针的类型和指针的运算(一)
2018-04-08 08:51:15 】 浏览:290
Tags:入门教程 指针 类型 运算

void *

在上一篇教程中,你可能会有疑问,为什么不用统一的指针类型,而用不同类型后面加*作为指针的类型。而实际上,你可以用void *类型的变量来保存所有的内存地址:

#include 
  
   

int main(void)
{
    int value = 100;
    void *pointer = &value;
    std::cout << "变量value的地址:" << &value << std::endl;
    std::cout << "指针pointer保存的值:" << pointer << std::endl;
    return 0;
}

  

所有类型的指针都可以不需要转换直接赋值到void *类型的指针,像这样:

int value = 100;
int *intpointer = &value;
void *pointer = intpointer;

但是当其他类型互转或者void *转换其他类型时,就需要用到类型转换:

int value = 100;
void *pointer = &value;

// 无类型指针转换到其他指针用static_cast转换, 不转换而直接赋值将会编译报错
int *intpointer = static_cast
  
   (pointer);

// 其他类型指针互转需要用reinterpret_cast转换, 不转换而直接赋值将会编译报错
long *longpointer = reinterpret_cast
   
    (&value); 
   
  

通过地址修改内存中的数据

我知道你的疑问并没有得到解决:为什么指针有用类型区分。

我们知道,内存是逐个字节划分的,然后为每个字节的内存给一个编号,就是内存地址。以int为例,int一般是4个字节,那么内存地址就是按顺序连续的4个编号,这样为每个字节修改并不方便。为了更加方便地访问内存,只需要指定指针的类型,并且给出内存第1个字节的地址,编译器就会知道你需要修改的是哪些位置的内存。同样,你使用取地址符&获取到int变量的地址,也是这个变量的第1个字节的地址。(第1个字节的地址下面将简称为首地址。)

说了这么多,现在看看怎样通过地址修改内存中的数据。只需要在地址前面加上*,就可以对这个内存中的数据进行操作:

#include 
  
   

int main(void)
{
    int value = 100;
    std::cout << *(&value) << std::endl;
    return 0;
}

  

输出结果:

100

上面代码中,先取出变量value的地址&value,然后在地址前面加上*即*(&value),这样就可以使用内存中的数据了,其中*(&value)加()是为了让它先取地址。

也可以将内存地址保存到指针里,然后再通过指针操作内存中的数据,如:

#include 
  
   

int main(void)
{
    int value = 100;
    int *pointer = &value; // 取出value的首地址赋值给pointer
    *pointer = 1024; // 在地址前加*就可以对地址代表的内存进行操作
    std::cout << value << std::endl; // value的值也随之改变
    return 0;
}

  

输出结果:

1024

由于编译器知道*(&value)和*pointer表示的这份内存是int类型(有4个字节),所以它会将从首地址开始的4个字节一起处理。所以如果你不指定地址和指针的类型,编译器就不知道你要操作哪几个字节的内存。也就是使用void *的话,编译器就不知道这份内存有几个字节。

const

现在看看const限制指针。

如果想指针初始化保存一个地址之后就不能再保存其他内存地址,可以这样写:

std::string text1 = "小古银的C++教程";
std::string text2 = "C++的小古银教程";
std::string * const pointer = &text1;
// pointer = &text2; // 去掉开头注释将会有编译错误

如果想指针指向的内存中的数据不被改变,可以这样写:

std::string text1 = "小古银的C++教程";
std::string text2 = "C++的小古银教程";
const std::string *pointer = &text1;
pointer = &text2; // 可以改变pointer保存的值
// *pointer = "小古银是死肥宅"; // 去掉开头注释将会有编译错误, 因为编译器知道我不是死肥宅

如果既不想改变指针保存的地址,也不想改变指针指向内存中的数据,可以这样写:

std::string text1 = "小古银的C++教程";
std::string text2 = "C++的小古银教程";
const std::string * const pointer = &text1;
// pointer = &text2; // 去掉开头注释将会有编译错误
// *pointer = "小古银是死肥宅"; // 去掉开头注释将会有编译错误

指针的运算

指针可以进行加减运算。和普通的数值运算不同,先看一个例子就会明白了:

#include 
  
   

int main(void)
{
    int value = 100;
    int *pointer = &value;
    std::cout << "pointer保存的地址:" << pointer << std::endl;
    std::cout << "pointer保存的地址加1:" << (pointer + 1) << std::endl;
    return 0;
}

  

当你看到输出结果的时候,你会发现两个地址的差值是4个字节。因为编译器是根据指针的类型来进行加减运算,也因此void *类型的指针是不能进行加减运算的。当然,你不应该对value的下一个地址表示的内存进行操作,因为你不知道这个内存里到底保存里什么,而且你连这个地址指向的地方有没有内存你也不知道。

以int举例,指针的加减运算可以理解为:指针加1,就是下一个int类型变量的首地址;指针加2,就是下下一个int类型变量的首地址;指针减1,就是上一个int类型变量的首地址;指针减2,就是上上一个int类型变量的首地址;以此类推。

指针的运算只能是加法和减法,而且在加法中指针只能和整数相加;在减法中,指针只能减去一个整数,或者两个指针相减。

特殊地pointer = pointer + n;(其中n是一个整数变量)可以

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇C++运算符重载教程 下一篇C++入门教程之内存和指针

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目