【指针与数组/Pointer and Array】

int arr[5];
int *ptr = arr;

 一、数组与指针

        当我们创建一个数组时,需要规定元素类型数组名以及数组的大小,然后程序会申请一块连续的内存用于存放数组。

        数组名代表了数组首个元素的地址,这是一个十分关键的概念。基于这个概念,我们很自然都就得出下面这组关系:

                                                        &arr[i] <=> arr+i

                                                         arr[i]  <=> *(arr+i) 

        似乎这样来看数组名就是指针,但是不像指针变量可以进行赋值操作,数组名代表一个数组的首个元素的地址,因此数组名应当被看作一个常量,无法进行赋值操作。想象你创建了一个数组,但是数组名的值被改变了,我们再想要对数组中的元素进行操作时,已经找不到当初数组创建时的那块连续的内存,因此数组名虽然是一个地址,但是其本身不能被修改。

ptr++;    //valid
arr++;    //invalid

二、数组作为函数参数

        当数组作为函数的参数传入时,编译器并不会复制一份数组的副本传入函数,取而代之是将数组的首个元素的地址传入函数。这是因为数组可能很大,复制一个数组的副本对内存并不友好。下面两种写法没有区别,或者说写法二更加准确,因为编译器会将写法一解释为写法二。

int func(int A[]){    //写法一

}

int func(int* A){     //写法二

}

三、指针和字符数组

        在C语言中,字符串以字符数组的形式存在。数组大小 = 字符串中字符的个数+1,这是因为需要最后一个元素等于 '\0' 作为标识代表字符串结束

        此处的 '\0' ,是字符串类型,占用一个Byte,ASCII值是0;注意区分整数 0 ,int类型,一般占4个Bytes,以及'0',字符0,ACSII值是48

        下面是字符数组的一些初始化方式:

char C[6] = {'H','e','l','l','o','\0'};      //数组大小最少是6
char C[] = "Hello";                          //数组大小为6 编译器会自动在末尾补上'\0'
char C[20] = "Hello";                        //数组大小为20 编译器会自动在C[5]补上'\0'
//char C[5] = "Hello";                       //invalid 数组大小不够

四、指针和二维/多维数组

        1、二维数组

        二维/多维数组在内存中仍是占用连续的一块内存。

int B[3][4];

        数组名是数组首个元素的首地址,这点十分重要。对于二维数组B来说,B有3个元素,B[0]、B[1]、B[2],而这3个元素都是拥有4个元素的一维数组。

        结合图片,理解上面两点应该更加清晰。当数组是二维甚至多维时,指针的使用需要注意。数组名B,表示的是B的首个元素的首地址,而B的首个元素是B[0],所以B等于B[0]的首地址。此时如果我们希望通过一个指针保存B,需要注意指针的类型。

int B[3][4];
//int *ptr1 = B;      //invalid
int (*ptr)[4] = B;    //valid

        指针的类型很重要,因为指针在解引用时,需要知道内存里存储的数据类型,只有这样才能正确解引用内存里的数据。

        而B中存储的元素是一维数组,并且是拥有四个元素的一维数组,并不是整型。因此,可以存储B的地址的指针类型为 int (*)[4] 。

        对于数组B来说,*B <=> B[0] <=> &B[0][0] ,这三者是相同的。结合指针算术运算的知识,我们也能得出,*(B+1) <=> B[1] <=> &B[1][0] 。其中B和(B+1)对应的指针类型为int (*)[4],B[0]和B[1]对应的指针类型为int *

        对于一个二维数组 B[i][j] = *(B[i]+j) = *(*(B+i)+j)

        2、多维数组

        多维数组实际上是数组的数组,比如三维数组就是拥有若干个二维数组为元素的数组。在解引用操作时,套用了更多层,使用的时候要注意。多维数组的初始化方式:

int C[3][2][2] = {{{2,5},{3,9}},
                  {{3,4},{6,5}},
                  {{1,0},{5,7}}};

        需要注意一下,当函数接收二维或多维数组时的写法。

//一维数组
void func(int A[]){
}
void func(int *A){
}

//二维数组,最底层的一维数组的大小不能被省略
void func(int A[][2]){
}
void func(int (*A)[2]){
}

//三维数组,最底层的一维数组的大小不能被省略
void func(int A[][2][2]){
}
void func(int (*A)[2][2]){
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值