数组传递给函数参数
C++函数传递数组,自动转换为相应的指针类型(数组起始地址),且无边界检测。
定义形参时,可以定义边界,也可以为空。
例如:
void func(int a[4]);//使用此函数时形参数组边界被定义为4
void func(int a[]);//无边界,使用时需要注意
void func(int* a);//可以当作无边界数组使用指针a
注意! 由于传递地址,所以传递使用数组时会实际改变数组的值
C++不能返回数组,只能返回相应类型的指针。
如果你确定你操作的指针是一块数组内存,那么可以对该指针进行下标操作
数组指针与指针数组
int* p[10] ; //指针数组 10个int* , 每个元素指向一个int
main函数就是一个例子
int main(int argc , char* argv[] );
argv每个元素指向一个char*类型
int (*p)[10] ; //数组指针 一个int数组指针,指向一个含有10个元素的数组
用数组指针传值可以操作二维数组的第二级数组
void func(int (*p)[] );
int a[3][4];
func( a[2] );
数组与指针的关系
数组名是一个常量,所以不能修改。
首先,数组与指针不是一种类型。数组是一系列连续的内存,指针只指向一个元素的内存。
在使用数组时,编译器都会自动将其转换成一个指向数组首元素的地址。(参考数组传参)
可以将数组名赋值给一个指针,这个指针可以作为数组的迭代器。
看个例子:
//1
int a[10];
int b;
int *c;
int* p = a;//指向数组首元素
int (*p)[10] = a;//指向整个数组
p++; //现在p指向a[1]
sizeof(a);// 40 10个int大小
sizeof(b);// 4 1个int大小
sizeof(c);// 8 1个指针大小
在学习C语言时,通过malloc分配一块连续的内存,返回一个指向该内存起始位置的指针
这个指针就可以当作数组或者迭代器使用
C++11后引入了两个函数begin和end,他们分别返回指向第一个元素位置的指针,和最后一个元素之后的位置
用法:
int a[] = { ...... };
int* beg = begin( a );
多维数组
C++并不存在多维数组
多维数组就是数组的数组,在一维数组存放一维数组就是二维数组
多级数组中:
char *p = a; //指向类型为char*
char (*p2)[] = a[0]; //指向类型为char*[]
char (*p3)[][] = a[0][0];//指向类型为char*[][]
需要注意,char**并不是指向char*[],而是指向“指向char*的指针”,这是两种不同的类型
char *p;
char **p2 = &p; //二级指针
char ***p3 = &p2; //三级指针
指针操作多维数组:
主要看指针是指向第几层(层数由里向外)的指针,就需要解几次引用
例子:
int a[2][3] = {1,2,3,4,5,6};
int *p = a[0];
int (*p2)[3] = a;
cout << *(++p) << endl;
cout << **(++p2) << endl;
因为p指向int类型,所以++p横向后移一个元素指向2,
p2指向int[3]类型,p2指向int[3],++p2纵向移动一个元素指向4,第一次解引用(*)int[3]类型,第二次解引用int
如果 *((*p)+1) 先解引用int[3],指向第二层(int*),对第二层进行+1,横向移动,最终指向2
结语
C++数组虽然一般用Vector等替代,vector也有更好的使用体验,比如动态添加元素之类的
在性能和灵活性的权衡上,因为数组大小固定不可变,因此对某些程序某些情况可能运行实效更好
如有错误欢迎指正
先到这里,以后发现啥再补充
补充 2018-5-19:
C++中数组可以越界访问,访问数组的本质是,访问一段连续内存中的某个单元,只要这个单元的内存是可用的,那么程序就不会崩溃,但访问来的元素是未知的。而会导致内存不可用的原因,通常是操作系统的内存保护机制,也就是说程序会因为访问未分配给他的内存而崩溃,也就是访问的元素超出系统分配的区域。
例如:
int a[5] = {1,2,3,4,5};
std::cout << a[9];
这里将a数组向后第10个int位置的内存当作int类型访问,访问结果是未知的。
写程序时一定要仔细,这种bug叫未定义行为,编译器一般是放行的,所以排查极其困难,避免这种错误发生是程序员的责任!
补充 2018-6-26:
char* 相似于char[ ],但他们并不相同。
char[ ]可以直接赋值字符串,char* 一般只能引用 &char[ ]
或者char* 要修饰为const 才能直接用字符串“adasdad”复制。