【C语言复习(十三)】数组和指针

1、数组本质回顾

数组是一段连续的内存空间;

数组的空间大小为:sizeof(ArrayType)*ArraySize

数组名可以看作指向数组首元素的常量指针;

2、指针的运算

2.1指针与整数的运算

运算规则为:

p+n;==(unsigned int )p+n*sizeof(*p);

2.2指针与指针的运算

指针之间只支持减法运算,且参与运算的指针类型必须相同:

运算规则为:

P1-p2;==((unsigned int)p1-(unsigned int)p2)/sizeof(type);

当两个指针指向同一个数组中的元素时,指针相减才有意义,得到的差是指针所指元素的下标差;

当两个指针指向的元素不在同一个数组中时,结果无意义

 

2.3 指针的关系运算

指针关系运算的前提是同时指向同一个数组中的元素,然后就可以进行关系运算;

指针之间可进行关系运算:<  <=  >  >=  ==  != ;前四个其实比较的是指针所指元素的下标,

后两个可在任意两个指针之间的(==!=)运算,无限制!

 

3、数组元素的访问

3.1 以下标形式

这种形式很常见,例如:

int a[5]={1,2,3,4,5};

a[0]=a[0]+1;

a[1]=a[1]+1;

这里实际上会做指针与整数的运算,a[1]=(unsigned int)a+sizeof(type)*1;

3.2 以指针形式

基于数组名是数组首元素地址,例如:

int a[5];

*a=1;

*(a+1)=2;

实际上这里会先做指针与整数之间的加法运算,得出地址;运算规则如上所述:*(a+1)=*((unsigned int)a+sizeof(type)*1)

 

3.3 下标VS 指针 谁更好?

从理论上而言,当指针以固定增量在数组中移动时,其效率高于使用下标的代码;

当指针增量为1且硬件具有硬件增量模型时,表现更好!

现代编译器生成代码优化率已经大大提高,在固定增量时,下标形式的效率已经和指针形式相当;但从可读性和代码维护性的角度看,下标形式更好一点;

 

4、a&a的区别

如果有如下定义

int a[5];

那么,a为数组首元素地址;

&a为整个数组的起始地址;

它们的值虽然一样,但是意义不一样,具体的区别就在于指针运算:

a+1;===> (unsigned int)a+sizeof(*a)*1

&a+1;===>(unsigned int)(&a)+sizeof(*(&a))*1=(unsigned int)(&a)+sizeof(a)*1

因为*&互为逆运算;

 

5、指针运算经典面试题

计算输出结果?

#include <stdio.h>
 
int main()
{
    int a[5] = {1, 2, 3, 4, 5};
    int* p1 = (int*)(&a + 1);
    int* p2 = (int*)((int)a + 1);
    int* p3 = (int*)(a + 1);
 
    printf("%d, 0x%08X, %d\n", p1[-1], p2[0], p3[1]);
 
    return 0;
}

计算方法分析:

首先要分别计算出p1p2p3的值:

假设a的起始地址为:10;即是a的首元素地址为10

p1= (int*)(&a + 1);==> (unsigned int)(&a)+sizeof(*(&a))*1==10+sizeof(a)*1=10+20=30;

P2=(int*)((int)a + 1);==>(int)a+1=10+1=11;

P3=(int*)(a + 1);==>(unsigned int)a+sizeof(*a)*1=10+4=14;

则:

p1[-1]=(unsigned int)p1+sizeof(int)*(-1)=30+(-4)=26;

p2[0]=(unsigned int)p2+sizeof(int)*0=11;

P3[1]=(unsigned int)p3+sizeof(int)*1=14+4=18;

详细分析看图:


 

6、数组做为函数参数

C语言中,如果一个函数传入的参数是一个数组,那么编译器将会把这个参数编译成对应的指针,到了函数内部,它就不再是一个数组,而仅仅是一个指针;

void func(int a[]); ==> void func(int *a);

void func(int a[5]);==> void func(init *a)

 看上面的函数定义,虽然我们定义了形参数组有5个元素,但是经过编译,实际上在func函数内部并不能得到这个数组的大小5;如下示例:

#include <stdio.h>
 
#define DIM(array)   (sizeof(array)/sizeof(*array))
 
int fun_size(int num[500])
{
    return DIM(num);
}
 
int main()
{
    int a[5] = {1, 2, 3, 4, 5};
    printf("a数组的大小:%d\tfunc函数计算的大小:%d\n",DIM(a),fun_size(a));
    return 0;
}

运行结果:


 

7、指针和数组的对比

  • 数组声明时编译器自动分配一片连续的内存空间;
  • 指针声明时只分配用于容纳指针的4个字节的空间;
  • 在作为函数参数时,数组参数和指针参数等价;
  • 数组名在多数情况下可以看作常量指针,其值不能改变;
  • 指针本质是变量,保存在其中的值被看作内存中的地址;

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值