一维数组:int a[c],其中a是数组名称,c是数组维度,数组维度必须是常量表达式!例如:
1 int c=3; 2 int a[c];//错误!由于c不是常量表达式,所以该定义非法。若将c定义为const int,即c成为一个常量表达式,则可正常编译。
数组的初始化:
int a[3]={1,2};//正确!等价于a[3]={1,2,0} int b[3]={1,2,3,4};//错误!初始值过多。 int c[]={1,2};//正确!等价于c[2]={1,2} string d[3]={"hi","bye"};//正确!等价于d[3]={“"hi","bye",”“} //字符数组的特殊性:一定要注意字符串字面值得结尾处还有一个空字符! char e[]={"C++"};//自动在字符串结束出添加空字符! char e[3]={"C++"}//错误!没有空间可存放空字符! //不允许拷贝和赋值int f[]={1,2};int g[]=f;//错误!不允许用一个数组初始化另一个数组。g=f;//错误,不能把一个数组赋值给另一个数组。
数组元素的访问可以通过数组名+下标号访问,此处应注意的问题是数组的下标是否在合理范围之内(这是有程序员负责检查的),当下标越界的时候,会引起一种严重的程序故障:缓冲区溢出(buffer overflow)。
在用到数组名的地方,编译器会自动地将其替换成一个指向数组首元素的指针。从一个指针加上或减去一个整数,结果仍然是指针,新指针指向的元素与原来的指针相比前进或后退了该整数个位置!
资料:
数组名的本质是代表数组对象的变量名,是一个左值,是一个不能被改变的左值。但是由于在程序中不保存数组的大小,所以通过数组名只能访问数组的左值,不能访问数组的右值。由于这个原因,数组名在作为右值使用的时候被赋予另外一个新的意义——指向数组第一个元素的指针,这就是 array-to-pointer 转换规则。 数组名在程序中作为左值使用的情况屈指可数——在大部分情况下数组名都是作为右值使用的,这时它是一个指针,一个指向数组第一个元素的指针,一个指向不能再被改变的指针——因此是一个指针常量。 那么数组名在什么情况下作为左值使用的呢?根据标准的规定,只有当数组名作为sizeof、&运算符的操作数的时候,它是一个左值,类型为数组类型;除此之外的所有情况,数组名都是一个右值,被编译器自动转换为指针类型,这种情况下我们就说数组名是一个指针,并且是一个指针常量。 单纯地说数组名是一个指针是片面的。我们通常说数组名是一个指针是建立在一个前提的基础之上的,那就是:数组名作为右值使用的时候。 对于数组名总结如下: 在作为左值使用的时候,数组名表示数组对象,是数组类型。在作为右值使用的时候,数组名是一个指针,是指针类型,不再是数组类型。数组名到底是数组还是指针取决于其上下文环境。
PS:左值指的是能够出现在等号左边及右边的变量(表达式),右值则指的是只能出现在等号右边的变量(表达式)。左值就是在程序中能够寻址的东西,右值就是没法取到它的地址的东西(不完全准确)。
二维数组:c++中实际上并没有多维数组,通常所说的多维数组本质上是数组的数组!!! 例如,int a[2][3]={{1,2,3},{4,5,6}}表示一个大小为2的数组,每个元素是含有3个整数的数组。
首先强调一下指针的概念(C++指针详解),不能简单把指针看成地址,不要忽略掉数据类型。也就是说一个指针包含两方面,一个是地址,一个是数据类型。指针是变量,这个变量的值是个地址。变量的类型是指向一个数据类型。可能有两个指针的值一样但是他们其实是不一样的,因为他们指向的数据类型不一样,此时使用取内容符号*取得的东西就会不一样了。例如:对于二维数组int a[2][3]={1,2,3,4,5,6},a是一个指针,a[0]也是一个指针,并且这两个指针的值是一样的,但是它们的数据类型不同!所以对它们用*取内容所得结果也不一样,*a[0]是一个整数:1。因为a[0]就是指向的类型就是整数,占4个字节。使用*a[0]以后,系统会从a[0]开始往后取4个字节。然后把这4个字节的内容转化为一个整数也就是我们的a[0][0]了;*a是一个地址。因为a指向的是一个大小为3的整数数组:{1,2,3},*a表示的就是a[0]。此外还有指针的运算问题:注意*(p+n)恒等与p[n]! a+1还是个指针,指向的数据类型也不变,不过他的值变成a+sizeof(a所指向的数据类型),也就是到了a这个指针的值往后跳一个它所指数据类型这么大小的那个内存地址。而a[0]+1则表示a[0]指向的值得下一个整数!
例子:
int a[2][3]={0,1,2,3,4,5};
cout<<sizeof(a)<<std::endl;
cout<<*a<<endl;//输出结果等于a[0]的地址,即{0,1,2}的地址。
cout<<**a<<endl;//输出0
cout<<a[0]<<endl;//输出a[0][0]的地址。
cout<<*a[0]<<endl;//输出0
cout<<*a[1]<<endl;//输出3
cout<<**(a+1)<<endl;//输出3
cout<<*(a[0]+1)<<endl;//输出1