您的位置:首页 > 编程语言 > C语言/C++

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

2016-12-05 18:23 411 查看
这几天看《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];
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c++