(81)数组的声明
数据类型数组变量名[个数常量];
因为数组占用的内存空间大小必须在程序编译时决定,并且一旦决定了,就不能再改变。所以只能用常量来指明数组的大小。当然,这是指在数据区或栈区分配内存,如果是在堆区,则可以动态地分配数组的大小。
由于SIZE是确定的,在编译之前就被替换,所以是对的;
第二个则属于动态定义,因为运行时才能知道数组该开辟多大,这种定义是非法的!
(82)数组至少会有一个元素
例如int arr[0];会报错error C2466: 不能分配常量大小为0 的数组。
(83)数组的初始化
对于数组变量,只能在定义时,对整个数组赋初值。
(84)数组的赋值
定义以后不能对数组整体赋值,只能对单个元素进行直接操作。
int arr[5];
arr[5] = {1,2,3,4,5}; //错
//或
arr = {1,2,3,4,5}; //错
可以采用以下方式改变数组中第一个元素的值:
arr[0] =100;
(85)两个数组不可以相互赋值
可以用一个循环来实现将一个数组内的值一个一个全部赋值给另一个数组,这也称为数组间的拷贝。
因为数组名是数组首元素的内存地址,是一个常量,不能被赋值。
(86)数组的输入输出
输入:由于数组名是数组首元素的内存地址,是一个常量,不能被赋值。一维数值型数组,要对数组各元素操作,不能直接用数组名操作。
int i ,arr[5];
不能用
cin >> arr;
而是用
for (i = 0; i <5;i++)
cin>> arr[i];
输出:int arr[5] = {1,2,3,4,5};
cout << arr; //并不能输出arr内5个元素的内容。
编译并没有报错。程序也可以运行。但是输出的是数组中第一个元素的内存地址。正确方式也是用一个循环将元素一个一个的输出。
(87)数组占用内存空间
某个数组占用了多少个字节,是数组元素个数*每个元素占用的字节。即:
int arr[5];
cout << sizeof(arr) << endl;//5*sizeof(int)
bool arr1[5];
cout << sizeof(arr1) << endl;//5*sizeof(bool)
为什么cin不知道arr的尺寸,而sizeof却可以得知?因为sizeof事实上是在编译阶段就进行计算。
(88)指向第一个元素的指针与指向整个数组的指针
ip和pa指向同一地址,但是ip和pa指向的对象不同。a是指向数组中第一个元素的指针,&a是指向整个数组的指针。
int *p[3];
(ii)int (*q)[3];
(iii)int *(t[3]);
以上三者的区别?
(1)p是一个指针数组,此处包含三个整型指针,所以sizeof(p) =12; sizeof(*p) = 4;//首地址
q是一个数组指针,指向含有三个元素的整型数组,所以sizeof(q) =4;sizeof(*q)=12;
t和p一样;sizeof(t) =12;sizeof(*t) =4;
(2)int *p[3]等价于:typedef int* myint;
myint p[3];
int (*p)[3]等价于:typedef int intarray[3];
intarray *p;
(3)(i)可以这样初试化:int a[]= {1,2,3,4};
p[0]= a;//*p = a;
(ii)可以这样初始化:int a[3]= {1,2,3};//数组元素必须是三个
q= &a;
(4)p是数组,不可做++操作,q是指针,可以做++操作,q++是当前q指向的地址值加12;
(89)动态数组的声明
int *ip = new int[10];
注意是中括号而不是大括号,大括号表示ip指向一个被初始化成10的整数。
(90)数组形参
因为数组会被自动转化为指针,所以处理数组的函数通常通过操纵指向数组指向数组中的元素的指针来处理数组。
如果要编写一个函数,输出int型数组的内容,可用下面三种方式指定数组形参:
void printValues(int*) { /* ... */ }
void printValues(int[]) { /* ... */ }
void printValues(int[10]) { /* ... */}
上面的三种定义是等价的,形参类型都是 int*。
通常,将数组形参直接定义为指针要比使用数组语法定义更好。这样就明确地表示,函数操纵的是指向数组元素的指针,而不是数组本身。由于忽略了数组长度,形参定义中如果包含了数组长度则特别容易引起误解。
(86)数组的输入输出
输入:由于数组名是数组首元素的内存地址,是一个常量,不能被赋值。一维数值型数组,要对数组各元素操作,不能直接用数组名操作。
int i ,arr[5];
不能用
cin >> arr;
而是用
for (i = 0; i <5;i++)
cin>> arr[i];
输出:int arr[5] = {1,2,3,4,5};
cout << arr; //并不能输出arr内5个元素的内容。
编译并没有报错。程序也可以运行。但是输出的是数组中第一个元素的内存地址。正确方式也是用一个循环将元素一个一个的输出。
(87)数组占用内存空间
某个数组占用了多少个字节,是数组元素个数*每个元素占用的字节。即:
int arr[5];
cout << sizeof(arr) << endl;//5*sizeof(int)
bool arr1[5];
cout << sizeof(arr1) << endl;//5*sizeof(bool)
为什么cin不知道arr的尺寸,而sizeof却可以得知?因为sizeof事实上是在编译阶段就进行计算。
(88)指向第一个元素的指针与指向整个数组的指针
ip和pa指向同一地址,但是ip和pa指向的对象不同。a是指向数组中第一个元素的指针,&a是指向整个数组的指针。
int *p[3];
(ii)int (*q)[3];
(iii)int *(t[3]);
以上三者的区别?
(1)p是一个指针数组,此处包含三个整型指针,所以sizeof(p) =12; sizeof(*p) = 4;//首地址
q是一个数组指针,指向含有三个元素的整型数组,所以sizeof(q) =4;sizeof(*q)=12;
t和p一样;sizeof(t) =12;sizeof(*t) =4;
(2)int *p[3]等价于:typedef int* myint;
myint p[3];
int (*p)[3]等价于:typedef int intarray[3];
intarray *p;
(3)(i)可以这样初试化:int a[]= {1,2,3,4};
p[0]= a;//*p = a;
(ii)可以这样初始化:int a[3]= {1,2,3};//数组元素必须是三个
q= &a;
(4)p是数组,不可做++操作,q是指针,可以做++操作,q++是当前q指向的地址值加12;
(89)动态数组的声明
int *ip = new int[10];
注意是中括号而不是大括号,大括号表示ip指向一个被初始化成10的整数。
(90)数组形参
因为数组会被自动转化为指针,所以处理数组的函数通常通过操纵指向数组指向数组中的元素的指针来处理数组。
如果要编写一个函数,输出int型数组的内容,可用下面三种方式指定数组形参:
void printValues(int*) { /* ... */ }
void printValues(int[]) { /* ... */ }
void printValues(int[10]) { /* ... */}
上面的三种定义是等价的,形参类型都是 int*。
通常,将数组形参直接定义为指针要比使用数组语法定义更好。这样就明确地表示,函数操纵的是指向数组元素的指针,而不是数组本身。由于忽略了数组长度,形参定义中如果包含了数组长度则特别容易引起误解。