C++ 数组与指针

一、数组形参

数组在传入时,实际上只传入指向其首元素的指针。数组在“退化”时会丢失边界。

void average(int ary[12]); //形参ary是一个int *
//...
int anArray[] = {1,2,3};
average(anArray); //合法

void average(int ary[], int size); //传统的做法是将数组大小传入

如果数组边界的精确数组很重要,并且希望函数只接受含特定数量的元素的数组,可以考虑引用形参

void average(int (&ary)[12]); //只接受大小为12的int数组
average(anArray); //错误!anArray是int[3]

多维数组形参,只是第一维数组退化为指针,后面的维数边界没有退化,否则无法对形参执行指针算术

void process(int ary[10][20]);
void process(int (*ary)[20]); //ary是一个指针,指向一个大小为20的int数组
void process(int ary[][20]); //建议定义为这样,更清晰

二、指针算术

指针+1不是将指针的地址增加一个字节,而是按照所指对象的大小比例进行,增加sizeOf()个字节。这也是void *不支持指针算术的原因,因为不知道指向对象的类型。

//一维数组
int ary[5] = {1,2,3,4,5};
int *ptr=(int*)(&ary+1); //&ary+1的单位是int(*)[5]
printf("%d\n%d\n",*(ary+1),*(ptr-1)); //结果 2 5
printf("sizeof(ary)=%d\n",sizeof(ary)); //结果 20
printf("sizeof(&ary)%d\n",sizeof(&ary)); //结果 4(32位系统)
/**
ary是数组首地址ary[0]的地址,&ary是对象(数组)首地址;
ary+1是数组下一个元素的地址,即ary[1];而&ary+1是下一个对象的地址,即ary[5]。
sizeof(ary) 是 数组的空间大小,即 5 * 4 = 20;
sizeof(&ary),&ary是一个指向int型数据的指针
**/

//多维数组
int a[3][4];
int (*p)[4] = a; //p指向int[4]数组,所指对象大小是sizeof(int)*4,而不是一个int。

//a+i,a[i],*(a+i),&a[i][0]是等同的,都是第i个一维数组的首地址。
//&a[i]和a[i]也是等同的,二维数组不存在元素a[i]

//*(p+i)是一维数组a[i][0]的地址; *(p+2)+3表示a[2][3]地址,*(*(p+2)+3)表示a[2][3]的值。

同类型的指针可以做减法运算,结果为两个指针之间的元素个数(而不是它们之间的字节数)

三、数组指针和指针数组

数组指针:是一个指针,指向一个数组

指针数组:是一个数组,数组元素是指针

int *p1[10]; //指针数组。[]的优先级比*高,p1[]构成一个数组,int*是数组元素。p1是数组的名字,指向数组第一个元素。
int (*p2)[10]; //数组指针。()优先级比[]高,*p2定义一个指针,int是数组元素。p2指向一个匿名的int[10]数组。

两者访问二维数组:

//数组指针
int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
int (*p)[4];
p = (int(*)[4])a;
for(int i=0; i<3; i++)
{
    for(int j=0;j<4;j++) printf("%d",p[i][j]); //或者 *(*(p+i)+j) 或者 *(p[i]+j)
    printf("\n");
}


//指针数组
int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
int *p[3];
for(int ix = 0; ix<3; ix++) p[ix] = a[ix];
for(int i=0; i<3; i++)
{
    for(int j=0;j<4;j++) printf("%d",p[i][j]); //或者 *(*(p+i)+j) 或者 *(p[i]+j)
    printf("\n");
}

四、常量指针和指针常量

常量指针:指针是常量

指针常量:指向常量的指针

T *pt = new T; //一个指向T的指针
const T *pct = pt; //一个指向const T的指针。等同于 T const* pct.
T *const cpt = pt; //一个const指针,指向T

const T *const cpct1 = pt; //一个指向常量的常量指针。等同T const *const cpct1

一个指向非常量的指针可以转换为一个指向常量的指针。但相反的转换是非法的。

const T acT;
pct = &acT;
pt = pct; //错误!
*pt = aT; //视图修改常量对象!

pt = const_cast<T *>(pct); //没有错,但这种做法不妥
*pt = aT; //视图修改常量对象!

五、函数指针

int *f1(); //一个返回值为int *的函数
void (*fp)(int); //fp是一个指向返回值为void, 参数为int的函数的指针

extern void h(int);
fp = h; //OK
fp = &h; //OK, &可有可无,通常省略

(*fp)(12); //显示解引用
fp(12); //隐式解引用,结果相同

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值