C++——指针学习

之前因为种种原因一直不愿意学指针(当然这是借口,其实是懒外加笨,无论是看书还是听课都没学会,直到上次C++实验课老师要求必须用指针写,我(╯‵□′)╯︵┻━┻)。


先从最基本的问题开始,我们每学一个知识,都要知道学这个知识是干什么的(无非是提升能力素养或者陶冶情操什么的),那么指针有什么用呢?

按照百度百科的说法:

在计算机科学中, 指针 (Pointer)是编程语言中的一个对象,利用地址,它的值直接指向(points to)存在电脑存储器中另一个地方的值。由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。

我特别能理解第一次接触这段话,并且还没有学过或者了解数据结构的小白的感受(因为我就是啊),看到这段话,其实是很懵的,完全不知所云。

好吧,那我们先来初步了解一下数据结构是什么?
首先是来自百度百科的标准定(fei)义(hua):数据结构是计算机存储、组织数据的方式。

下面是摘自数据在计算机中的存储的解释。
数据有数值型非数值两类,这些数据在计算机中都必须以二进制形式表示一串二进制数既可表示数量值,也可表示一个字符、汉字或其他。一串二进制数代表的数据不同,含义也不同。这些数据在计算机的存储设备中是如何进行组织存储的?

  数据单位

  位(bit)

  位(bit),音译为"比特",是计算机存储设备的最小单位,由数字0或1组成。

  字节(Byte)

  字节(Byte),简写为"B",音译为"拜特",简写为"B"。8个二进制位编为一组称为一个字节,即:1B=8bit。字节是计算机处理数据的基本单位,即以字节为单位解释信息。通常,一个ASCII码占1个字节;一个汉字国标码占2个字节;整数占2个字节;实数,即带有小数点的数,用4个字节组成浮点形式等

  字(word)

  计算机一次存取、处理和传输的数据长度称为字,即:一组二进制数码作为一个整体来参加运算或处理的单位。一个字通常由一个或多个字节构成,用来存放一条指令或一个数据。

  字长

  一个字中所包含的二进制数的位数称为字长。不同的计算机,字长是不同的,常用的字长有8位、16位、32位和64位等,也就是经常说的8位机、16位机、32位机或64位机。例如,一台计算机如果用8个二进制位表示一个字,就说该机是八位机,或者说它的字长是8位的;又如,一个字由两个字节组成,即16个二进制位,则字长为16位。字长是衡量计算机性能的一个重要标志。字长越长,一次处理的数字位数越大,速度也就越快。


  编址与地址

  编址

  对计算机存储单元编号的过程称为"编址",是以字节为单位进行的。

  地址

  存储单元的编号称为地址。

===》

1.内存中的每个位置都由一个独一无二的地址表示.
2.内存中的每个位置都包含一个值.
===》
我们可以通过一个地址,来找到内存中的某个具体位置,然后访问到(得到)该位置的值(允许的话).这就是内存和地址简单的思想.



其实……

用指针的原因就是因为……

方便……

当然,在知乎上也有很多解答,感兴趣的话可以去看看为什么要有指针


书归正传,先看一段代码:

/*指针学习。
之前一直固执的不学指针(其实是被oj吓的,以前刚刚学数组的时候就见到有报错,说我是数组越界或者是指针无意义,感到了无限的恐惧--->因此就没再学指针了)*/
#include<bits/stdc++.h>
using namespace std;
int main()
{
    int *a;
    int input;
    cin>>input;
    a=&input;
    cout<<a<<endl;
    cout<<*a<<endl;
    cout<<input<<endl;
    return 0;
}

第一行27是输入,第二行的0x69fef8就是地址,剩下两行都是数值。


那么问题来了,a和*a有什么区别?*a和input又有什么联系呢?


我们先看一下指针是如何声明的。


注:上面是截图,大家理解一下懒得打字的我。。。

附原文链接C++指针|菜鸟教程

总之,这个意思就是如果直接输出带*的那个变量的名字(而不带*号)得到的是地址,而加上*号得到的就是需要的那个值了,如果直接输出与&连接的变量名也会直接输出所需的值。


--------------------------到此就是我每次学习断开的地方------------------------------------

完全不知道这指针还有什么用,觉得还不如直接折腾a b来的简单(似乎,其实,好像……也确实,指针在除了C和C++里也没有哪里用了)。

直到上次C++实验课围观某大神用指针做题,我看的云里雾里,才坚定了我学习的心o(╥﹏╥)o



首先大家体谅一下好奇心旺盛到崩溃的我,忍不住试了一下如果写int a;不加*会怎么样。

结果是报错:

然后,尝试一下各种花式类型:

#include<bits/stdc++.h>
using namespace std;
int main()
{
    char *word;
    int *number;
    double *fla;
    string *str;
    char a;
    int b;
    double c;
    string d;
    cin>>a>>b>>c>>d;
    word=&a;
    number=&b;
    fla=&c;
    str=&d;
    cout<<a<<'\t'<<b<<'\t'<<c<<'\t'<<d<<'\n';
    cout<<word<<'\t'<<number<<'\t'<<fla<<'\t'<<str<<'\n';
    cout<<*word<<'\t'<<*number<<'\t'<<*fla<<'\t'<<*str<<'\n';
    return 0;
}


输入:

输出:

A 23 2.345 %zuzhang
A 0x7fff355ee59c 0x7fff355ee5a8 0x7fff355ee5a0
A 23 2.345 %zuzhang

接下来是一个作死的尝试,就是看这个*可以管多远(什么叫多远(╯‵□′)╯︵┻━┻)
然后是试图上面声明指针,下面不用……



作死完毕,进入正题(当然大家用的时候不要像上面一样)

指针和数组

指针和数组是密切相关的。事实上,指针和数组在很多情况下是可以互换的。例如,一个指向数组开头的指针,可以通过使用指针的算术运算或数组索引来访问数组。
#include <iostream>
 
using namespace std;
const int MAX = 3;
 
int main ()
{
   int  var[MAX] = {10, 100, 200};
   int  *ptr;
 
   // 指针中的数组地址
   ptr = var;
   for (int i = 0; i < MAX; i++)
   {
      cout << "var[" << i << "]的内存地址为 ";
      cout << ptr << endl;
 
      cout << "var[" << i << "] 的值为 ";
      cout << *ptr << endl;
 
      // 移动到下一个位置
      ptr++;
   }
   return 0;
}

当上面的代码被编译和执行时,它会产生下列结果:

var[0]的内存地址为 0x7fff59707adc
var[0] 的值为 10
var[1]的内存地址为 0x7fff59707ae0
var[1] 的值为 100
var[2]的内存地址为 0x7fff59707ae4
var[2] 的值为 200
然而,指针和数组并不是完全互换的。
#include <iostream>
 
using namespace std;
const int MAX = 3;
 
int main ()
{
   int  var[MAX] = {10, 100, 200};
 
   for (int i = 0; i < MAX; i++)
   {
      *var = i;    // 这是正确的语法
      var++;       // 这是不正确的
   }
   return 0;
}

把指针运算符 * 应用到 var 上是完全可以的,但修改 var 的值是非法的。这是因为 var 是一个指向数组开头的常量,不能作为左值。

由于一个数组名对应一个指针常量,只要不改变数组的值,仍然可以用指针形式的表达式。例如,下面是一个有效的语句,把 var[2] 赋值为 500:

*(var + 2) = 500;

上面的语句是有效的,且能成功编译,因为 var 未改变。



猜你喜欢

转载自blog.csdn.net/karen_yu_/article/details/78816229
今日推荐