它们很像vector和迭代器,C++程序尽量用vector和迭代器,除非有速度上的要求。
一、数组
数组是由类型名、标识符和维数组成的符合数据类型。
1.定义和初始化需要注意的地方
(1)数组长度是固定的,在编译之时就已确定好。
(2)数组的维数必须用值大于等于1的常量表达式定义(千万不能用变量),此常量表达式只能包含整型字面值常量、枚举常量、用常量表达式初始化的整型const对象。换句话说就是要满足两个条件:
- 为整型
- 在编译时就可以知道确切值(以便编译器为数组分配空间)
(3)数组元素初始化时,若没有显式提供元素初值,则元素会被想普通变量一样初始化:
- 函数体外定义的内置类型数组,元素初始化为0
- 函数体内定义的内置类型数组,元素无初始化(注意,若只初始化部分元素,其后的元素此时也会被初试化为0)
- 如果不是内置类型,则不管其在哪定义,自动调用其默认构造函数为其初始化;若该类无默认构造函数则会报错
#include<stdio.h> int a[3]={5};//5 0 0 int b[3];//0 0 0 void main() { int c[3]={5};//5 0 0 int d[3];//随机 }
(4)数组不支持直接赋值和复制。
2.数组操作
(1)数组下标从0开始,类型为size_t,下标不可越界(编译器并不检查)
(2)数组名其值为指向该数组的指针值(即数组首元素按的地址值),但数组名还包含着数组的长度,元素的类型两方面的信息。作为函数参数传递之后,退化为指针,丢失数组长度信息。
二、指针
指针其值为一内存地址,包含了两方面的信息:
-
指向的变量的地址
-
指向的变量的类型
它通常与 解引用(*) 和 取地址(&) 操作符密切相关。
1.定义与初始化
int * a; int* a; int *a;//上面定义三种都可以
而且,对于内置类型而言,int型指针只能指向int型变量。同一行定义两个指针必须这样:int *p1,*p2;不可这样:int * p1,p2。所以说,定义的风格还是统一为第三种的好。
指针值为0表示他不指向任何对象,可以通过数值0或在编译时值为0的const量以及NULL(cstdlib)来初始化,万不可通过整型变量来赋值,即使它可能为0。
另外不可使用没有initialize的指针变量,指针由同类型的变量地址或另一指针初始化,但也会有特例:
double obj = 3.14; void *Pd = &obj; //obj can be an object of any type
2.指针的操作
(1) 解引用生成左值
(2) 指针同引用的差别:这就像是指针常量与指针变量之间的差别,引用一旦定义必须初始化,之后它指向的对象就再不可改了。
(3) 指针可以指向指针
int ival = 1024; int *pi = &ival; int **ppi = π//ppi points to a pointer to int int *ppi = π//error,can't convert to "int *" from "int **"
(4) 可以使用指针访问数组元素:在表达式中使用数组名时,该名字会自动转换为指向数组第一个元素的指针,这时要注意指针的算术操作,指针可以+(-) n(int 型),两指针可想减,结果为ptrdiff_t类型(cstddef头文件),使用下标访问数组时,实际上是使用下标访问指针。
【例题】写出如下程序片段的输出。
int a[] = {1,2,3,4,5};
int *ptr = (int*)(&a+1);
printf("%d,%d",*(a+1),*(ptr-1));【答案】2,5
【解析】a看做指向int类型的指针,类型为int*;&a可看作指向int[]类型的指针,类型为int[]*。(&a+1)指向的是第六个位置(其实不存在)。数组名a代表指向数组首元素的地址,&a代表整个数组的地址。
3.const和指针
(1)指向const对象的指针——常量指针
下面两种方式定义都可以,推荐第一种。
const int *ptr1; int const *prt2;
ptr1,ptr2本身的值可以修改,所以在定义时可以不初始化,允许其被重新赋值而指向另一个对象。
另外注意,常量指针即“自以为指向const量”的指针:
把一个const对象的地址赋给一个非const对象的指针会导致编译出错 反过来,一个非const对象的地址赋给一个const对象的指针却是合法的,不可通过该指针修改基础对象,但可以通过别的方式修改。(2)const指针——指针常量
其本身的值不能修改。
int a=0; int *const pa=&a;
这意味着pa再也不能指向其他的对象。与任何const量一样,const指针也必须在定义时初始化。
4. 指针悬浮和内存泄露
(1) 指针悬浮,指针迷途或者 wild pointer 同指该指针指向的内存没有由程序分配到这个指针之上。
(2) 内存泄露通常是由系统将内存分配给指针,但之后指针却不再指向那个地方了。那块内存变成一块死内存了。
三、补充
1. 关于字符数组和字符指针
定义方法不同:
char str[10]; char *ptr;
赋值方法不同:
char str[10]; str = "china";//error strcpy(str, "china");//OK char *ptr; ptr = "china";
字符指针是变量,而数组名是地址常量。