数组与指针 ...

C++指针与数组详解
本文详细介绍了C++中的指针与数组的概念及其应用,包括指针的声明与初始化、指针运算、指针与数组的关系等内容,并通过实例帮助读者更好地理解和掌握。

    我之前也写过一篇“对C++中指针的简单理解”,因为也是刚开始写博客,感觉弄得乱糟糟的,而且有种断章取义的感觉。所以今天打算写得细致一点(其实也就是照着书上搬的)。提到数组与指针我想大多数同我这样的渣渣一样,都觉得不好弄懂。以前老师上课吧,也没认真听,而且都是断断续续地在讲。现在自己从图书管里面借了一本书来学习,终于大致弄懂了(估计也就是皮毛);不过掌握一点总比不会好吧。指针这个东西对于学语言(我所知的特别C和C++)都有特别大的用处。如果不学好,就会出现 有可能某一天你看别人写的代码,里面全是指针,顿时你就傻眼了。我写这个的目的也是为了巩固自己所学的,顺便就当做个笔记,以便于以后查看。说实话,这个东西如果你不经常用到,就算你今天弄懂了,可能隔几天又忘得差不多了。好了,费话扯得差不多了,就开始进入正题吧!


1.计算机中的内存

    说到指针就先简单说说计算机里面的内存是怎么回事吧。在计算机中,系统的内存就像是带有编号的小房间,如果想使用内存就需要得到房间号。如图1所示,定义一个整型变量i;之后计算机就分配给它4个字节,所以编译器为变量i 分配了编号从2001到2004的房间(这儿的编号只是我随意举例的,在计算机中地址一般类似于这样0044FA28,不过不影响我们对整体的理解);每个房间代表一个字节。


当为变量i=5赋值之后,就被连续地存储在系统的内存中,如图2所示(其实应该是2进制00000000 00000000 00000000  00000101)


    在程序执行时,是根据变量与地址的对应关系,找到变量i的地址2001,然后从2001开始读取4个字节的数据放到寄存器中。由于通过地址能访问指定的内存存储单元,我们就可以说该地址“指向”该内存单元,之后我们就可以把地址形象的称为指针,即一个变量的地址称为该变量的指针。这也就是对指针概念的引出。另外,如果有一个变量专门用来 存放另一个变量的地址,它就是指针变量(其实指针也是一个变量,只是它仅用于存储变量)。

2.指针的声明与初始化

声明格式:

数据类型 *指针变量名

如:int *p;

初始化:

a.在定义时初始化:

int i;

int *p=&i;    (其中&是取地址符,表示把i的地址取出来赋给p)

b.在定义之后赋值:

int i,*p;

p=&i;      (注意,这种情况下赋值的时候就不要*了)

例1:

#include <stdio.h>
void main()
{
    int i = 2015;
    int *p = &i;//初始化的时候把i的地址赋给p
    int *q;
    q = &i;//初始化之后再把i的地址赋给q
    printf("%d\n", *p);
    printf("%d\n", *p); // 此时输出的结果一样均为2015
}



注:其中p,q是变量名,*p,*q 表示取变量p,q所指向内存单元的值

3.&*p和*&i(i为一个整型变量)的区别

如:int i=2015;

int *p=&i;

    &和*的运算符优先级别相同,按自右向左的方向结合,因此&*p是先进行*运算,*p相当于变量i的值(2015),再进行&运算,&*p就相当于变量i的地址。*&i是先计算&运算答,&i就是取变量i的地址,然后进行*运算,*&a就相当于取变量i 所在地址的值(2015)。总之你只要记住两个运算符的作用,和结合方向就知道结果了!

4.指针的运算

   因为指针也是变量,所以同样可以进行运算(本处就仅限于+-吧,我想其实剩除也行只是对于初学者意义不大)。

   如图3所示,当定义变量i,j(int i=3,j=4),且此处假设计算机在分配内存的时候i,j变量之间是连续分配的(等后面说到数组的时候就更好理解了,这儿只是先提出一下)

    如果int *p=&i; 之后,p就指向了101,p++之后,则p就指向了105,此处的加1并不是从101到102的变化,而是加了一个单位的距离,可以理解成单位“1”;这个例子在计算机上基本上是不能实现的,因为在分配内存的时候,几乎不可以是这样连续分配的。说到数组之后就容易理解了。

5指针与数组

    先简单说一下什么是数组。数组,作为同名、同类型的元素的有序集合,被顺序存放在一块连续的内存中(注意这儿是连续,且不仅仅限于一维数组,N维数组在内存中也是是连续储存的,只是为人理解,人为的把它们的地址做了一些变化,如图4),而且每个元素的存储空间大小相同,比如是int 型的数组则每个元素的大小都是4个字节。(我只是搬运工哦,顺便加了一些自己的理解)


    如图4.1所示,在定义一个一维数组int a[7] 之后,数组a就被分配了等大小(都是4个字节)的7个连续空间,从301-307;此时的数组名a就代表该数组的首地址(301,等价于&a[0]);之后我们就可以通过使用数组名和下标的方式来引用数组里面的值。接着说二维数,如图4.2所示,定义了个二维数组int b[4][3],数组b就被分配了等大小(都是4个字节)的12个连续空间,从401-412;注意,这儿的数组名就不代表首地址了,b[0]才代表该数组的首地址(401,等价于&b[0][0]),同样我们可以通过数组名和下标的方式来使用数组。同时,为了我们方便理解,才把二维数组(n维也是一样的理解)转化成图4.3的形式。此时,我们可以分别把b[0],b[1],b[2],b[3]叫作该每一行的行地址。

注: (1)b[n]表示第n行的首地址;

     (2)&b[0][0]既可以看作是第0行的首地址,也可以看作是整个二维数组的首地址;同理&a[m][n]就表示第m行的第n个元素的地址;

     (3)*(b[n]+m)表示第m行第n列的值,因为b[n]代表第n行的首地址,然后再向右移动4个单位,再用*运算符,就表示它的值了

例2.

#include <stdio.h>

void main()
{
    int a[2][3] = {{1, 2, 3}, {4, 5, 6}};

    for(int i = 0; i < 6; i++)
        printf("%d ", *(a[0] + i)); //从首地址开始,一直往后移动
}



运行结果:

1 2 3 4 5 6 请按任意键继续. . .

6.指针的运算

    最后我们再来说说指针的运算。就拿我自己的接触来说,指针的运算更多的就是在数组里面。其它地方几乎也没见过指针有运算的,说到底就是因为其它地方的变量分配的地址不是连续的,所以运算也是没有意义的。

接着用图4来说

    在图4.1中,我们定义了一个数组a[7],且进行了初始化。此时再定义一个指针,int *p=a;(或int *p=&a[0]) 并把数组的首地址初始化为数组a的首地址,然后我们就可以通过指针p来操作数组了。

例3:

</pre><pre name="code" class="cpp">#include <stdio.h>
void main()
{
    int a[7] = {1, 2, 3, 4, 5, 6, 7};
    int *p = a;

    for(int i = 0; i < 7; i++)
        printf("%d ", *p++); //从首地址开始,一直往后移动
}

运行结果:

1 2 3 4 5 6 7 请按任意键继续. . .

注:(1)*p++ 相当于a[i++],表示输出p所指向的值之后,指针p下移一个单位(也就是4个字节,若定义的数组是long long a[7],单位长度就可能是8个字节了,一定要理解p+1的含义)

(2)*++p 相当于a[++i],表示指针先移动一个单位,然后输出p所指向的值

(3)*p++ 等价于 *(p++)  不要问为什么p++有括号之后就指针就应该先右移一个单位,再输出p指向的值,因为我也不知道,想那时还为这个和老师争了一下,让我自己拿电脑试,结果果然是这样。(开个玩笑,想知道为什么的可以去百度百度)

(4)同理*++p也等价于*(++p)

    在图4.2中,我们定义了一个二维数组b[4][3],并也进行了初始化;此时再定义一个指针int *p=b[0](或int *p=&b[0][0])并把数组的首地址初始化为数组a的首地址,然后我们就可以通过指针p来操作数组了,当然你也可以从中间截取如:int *p=b[2];

例4:


#include <stdio.h>

void main()
{
    int a[4][2] = {{1, 2}, {3, 4}, {5, 6}, {7, 8}};
    int *p = a[0];

    for(int i = 0; i < 8; i++)
        printf("%d ", *p++); //从首地址开始,一直往后移动

    p = a[2];
    printf("\n");

    for(int i = 0; i < 4; i++)//从第2行开始,一起往后移动
        printf("%d ", *p++);
}


1 2 3 4 5 6 7 8
5 6 7 8 请按任意键继续. . .



    好,数组与指针就先跟大家扯到这儿(不应该是和我自己扯到这儿,估计也没有看,留着以后自己慢慢回顾)! 未完待续!!!!!!!!!!

2015年4月9日11:34:25

转载于:https://www.cnblogs.com/tolic/p/7142277.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值