C++ 中复合类型声明的理解(尤其是指针数组/数组指针/多维数组的问题)

这几天看《C++ Primer》第五版感觉还是颇有收获的,澄清了之前很多不是很理解的概念,也知道了好多新用法
首先,先澄清一个误解,就是数组的定义问题,在C中C99标准之后数组定义时,数组的大小/维度是可以是非const的变量,而C++中,仍然只能用常量来定义数组大小。而一般编译器在做这些工作的时候都会忽略C++中只能用常量来定义数组的这个问题。导致我以为C++也有这个标准了呢。
其次,先理解简单的声明中的概念,int *p,注意int是一个基本类型, *,const,static,[]都是修饰符,用来修饰int的,默认要按照从右到左的顺序来判断其类型,
如int *p,首先应该看到定义了一个名为p的变量,然后再看到表示p是一个指针,然后是int,表明p是一个指向int类型的指针。
数组也是,int a[10],先看到[10]表明定义的是一个大小为10的数组,在看到a,表明数组名为a,然后再看到int,表明a是一个int类型大小为10的数组
下面就是符合类型声明,如果有括号要先看括号里的

int arr[10];
int *ptrs[10];
int (*Parray)[10] = &arr;           //也即C中定义/传递二维数组的方法
int (&arrRef)[10] =arr;          //数组的引用可以这么定义

第一个,非常简单不做解释了。
第二个,先看到[10],则表明其是一个大小为10的数组,数组名叫ptrs,然后再看到* 表明数组中的元素是指针,然后int表明指针类型为整型。
第三个,先看(*Parray)表明Parray是一个指针,然后再看[10]表明其是一个数组,然后这就说明了Parray是一个指向了大小为[10]的数组的指针。所以这里Parray是一个二维数组,因为Parrary指向了一个数组,而Parrary本身就是一个指针,所以其是一个二维数组。
第四个,类比于第三个的方法,就是(&arrRef)表明其是一个引用,然后[10]表明长度为10的数组,所以arrRef是一个长度为10的名叫arr的数组的引用。注意,第四种方法就是定义一个数组引用的方法

这里再说一下二维数组的问题

int a[3][2] = { {1,2}, {3,4} ,{5,6} };   
int *ptrs[3] = {a[0],a[1],a[2]};(2)
int(*ptrs2)[2] = a; 

用int ptrs[3],ptrs是一个长度为3的数组,数组中存的是一个int 的指针,所以其后的维度是二维数组第一维的维度,同时因为数组名不能用来给另外一个数组初始化的,一个数组【也被称为聚合对象】只能由{…}这种形式初始化。ptrs是一个数组名!所以需要用上面(2)中那样的方式初始化
而ptrs2就是一个指针,可以直接让其指向a就好,而此时a转换为指针类型的类型是int (*)[2],所以ptrs后面那个数组需要是a的第二个维度大小。更多维度的同理。

一定要注意,一个数组名字转化为指针时,判断其类型第一维大小是不考虑的,统一看成(*)。但是除第一维度之外,剩下的所有都要考虑。如

int m[3] = {1,2,3};
int *p_m = m;             //m去赋值时,把第一维换成*,就变成了int *,此时加不加括号一样的
int n[3][4] = {};
int (*)p_n[4] = n;           //n去赋值是,把第一维换成*之后,n的类型就变成了int (*)[4]
//这里再扯一个运算优先级的问题,为什么要加括号呢,因为第二优先级的符号都是从右到左进行结合的。
//而[] . -> () 是1级优先级,是最高的优先级,其是从左到右结合的
//++ & *  等等是2级优先级,其结合顺序是从右到左,所以才有 *ptr++ 这样的运算,表示指针先++,然后取值

函数参数传递也是同理

//当传递一维数组时,以下方式等价
int a[2];
void fun(int *a);
void fun(int a[]); 
void fun(int a[5]);   //这个里面不论写几都是一样的

//当传递二维数组时
int a[3][2]={};
void fun(int (*nums)[2])
void fun(int nums[][2]); 
void fun(int nums[5][2]);   //这个第一个维度里面不论写几都是一样的,fun在程序看来其参数类型就是int (*)[2]

当需要用到指针的指针时要下面这种方法:

int **pp = new int*[3];     //注意这个地方一定要初始化,如果不初始化下面没法赋值了。
pp[0] = a[0];
pp[1] = a[1];
pp[2] = a[2];
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值