2021-7-18 指针:强大而危险的灵魂【C++指针的应用---上】(炉边小坐)[19 日修改版]

对于指针,如果你不熟练,在某些情况下,最好去掉它。嗯,让派蒙回归应急食品。

——在提瓦特学C语言 第一章  旅途的起点:风起地——初识C语言

我在写关于C语言冒险的文章的时候,曾经提及过指针。指针(pointer),被誉为C/C++语言的灵魂。它可以通过指针获得变量的地址以及操纵地址,这是其他语言所缺乏的,强大的对硬件的操控力。很好,吹逼吹完了,那指针到底是什么? 

指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址。就像其他变量或常量一样,您必须在使用指针存储其他变量地址之前,对其进行声明。指针变量声明的一般形式为:

type *var-name; 翻译一下:类型名*变量名;

type 是指针的基类型,它必须是一个有效的 C++ 数据类型var-name 是指针变量的名称。用来声明指针的星号 * 与乘法中使用的星号是相同的。但是,在这个语句中,星号是用来指定一个变量是指针。例如:

int    *ip;    /* 一个整型的指针 */
double *dp;    /* 一个 double 型的指针 */
float  *fp;    /* 一个浮点型的指针 */
char   *ch;    /* 一个字符型的指针 */

所有指针的值的实际数据类型,不管是整型、浮点型、字符型,还是其他的数据类型,都是一样的,都是一个代表内存地址的长的十六进制数。是的,指针是一个储存地址的变量。我们不妨将指针打印一下:

#include <iostream>
 
using namespace std;
 
int main ()
{
   int  s1;
   char s2[10];
 
   cout << "s1 变量的地址: ";
   cout << &s1 << endl;
 
   cout << "s2 变量的地址: ";
   cout << &s2 << endl;
 
   return 0;
}

结果是:

s1 变量的地址: 0xbfebd5c0
s2 变量的地址: 0xbfebd5b6

这就是指针的本质。

好的,你一定会说,说了那么多,吹的那么厉害,到底怎么用呢?

我们建立一个指针包括了定义一个指针和给他赋初值,我们用&取地址符来取得变量的地址并存入指针中。之前介绍过,“*”是一个重载运算符,它既表示乘法,也用于定义指针,也可以做指针的间接引用,当指针间接引用时,它表示指针指向的变量的内容。你可能会问,为什么不直接引用一个变量而要绕一大个圈来通过指针来间接引用变量呢?我们下文在表。值得注意的是,*仅用于指针中,非指针无法使用间接引用操作符,*只能用于地址。

当然,间接引用的指针即可用于右值,也可用于左值,何谓左值右值呢?左值(lvalue)和右值(rvalue)这两概念是从 c 中传承而来的,左值表达式具有存放数据的空间且被允许存放。这就说明常量不可能充当左值,而右值则只能出现在右侧,左值两边皆可。

这里思考一下,既然指针是个变量,那指针有它自己的指针吗?答案是肯定的,指向指针的指针,成为二级指针。

我们初始化指针的时候,是不是要注明指针的类型?事实上,指针和所指向的数据是一一对应的,匹配的。但是指针值和所指向的数据类型有关吗?额,这个问题不太准确,应该说,一个int型的指针它的值是int型吗?

如果你在举棋不定,证明你落入了圈套了。指针值与数据类型无关,都是一个十六进制数表示的内存地址。而更重要的是,指针的类型有助于编译器读取与指向数据类型匹配的内存空间,这点尤为必要。例如两个不同类型的指针:int*iP和 float*fP

//pointer matching 2021-7-19-19:31
#include<iostream>
using namespace std;

int main()
{
    float f=34.6;
    float*fP=&f;
    int*iP=(int*)&f;//warning:将浮点数的地址赋给整型指针


    //out module(模块)
    cout<<f<<endl
        <<"iP: "<<iP<<"  "<<*iP<<"\n"
        <<"fP: "<<fP<<"  "<<*fP<<"\n";
    *iP=*fP;    //隐式数据转换,奇怪的是,在 CLion 里有可能会报错!但试过两次又顺利跑得动!
    cout<<f<<endl
    <<*iP<<endl
         <<*fP<<endl;
    return 0;


}

运行结果:

"/Users/yuwenao/C++ Learning/cmake-build-debug/untitled5"
34.6
iP: 0x3098feab8  1107977830
fP: 0x3098feab8  34.6
4.76441e-44
34
4.76441e-44

进程已结束,退出代码为 0

输出两个不同类型的指针结果确实一样的,都是 f 这个变量的地址,但是输出*iP的内容和*fP 的内容却不一样!这是因为尽管他们的地址是相同的,但不同指针类型告诉编译器要读取的内存数量不同,例如说 int 型指针就告诉编译器要读四个字节的数据啦,转换为整型输出啦,float 型指针就说要按照浮点型输出啦,我们叫变量为"一块被命名的内存"是非常恰当的,因为变量本身并不负责处理数据,它包含数据的类型等信息,交予编译器处理.所以*iP 中的内容是起始点为 f 的地址的一个实型数.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值