一、一维数组
1.1声明数组
- 类型 数组名[数组长度];
- 数组长度必须是整型常量表达式
1.2声明并初始化数组
- 类型 数组名[数组长度] = {初始化列表};
- 声明时可以不指明数组长度,编译器将根据初始化列表的长度作为数组长度
- 若初始化列表的初始值数少于数组长度,则其余元素均初始化为0
1.3访问数组元素
- 数组名[下标];
- 从0开始,不能越界访问,否则报错
- 数组不能进行整体赋值,整体比较以及char除外的整体I/O操作
- 遍历数组:for循环
1.4数组作为函数参数
- 要将数组名和数组长度作为实参
1.5从函数返回数组
- 返回数组名或指针
二、二维数组
2.1声明二维数组
- 类型 数组名[行数][列数];
- 行数和列数必须是整型常量表达式
2.2声明并初始化二维数组
- 类型 数组名[行数][列数] = {{初始化列表},{},..}; //内部嵌套的花括号是可选的
- 声明时可以不指定行数
- 数组在内存中一行一行存放
2.3访问二维数组元素
- 数组名[下标][下标];
- 遍历二维数组:for循环内再嵌套一个for循环
2.4二维数组作为函数参数
- 数组作为函数参数时,要将数组名和行数作为实参;被调用函数的第一个形参必须给出第二维的长度(即列数),且该列数需与实参的列数一致,第二个形参接收行数
2.5从函数返回二维数组
- 返回数组名或指针
三、指针
3.1指针常量(指针类型的常量,即指针本身就是一个常量)
- &变量名/常量名,代表存放该变量/常量的内存地址
- 数组名,数值上arr=&arr[0]
//指向变量XX的指针常量
//可以通过*ptr修改var1,*ptr也会随着var1的改变而改变,ptr不可以指向其他变量/常量
int var1 = 10;
int var2 = 20;
const int var3 = 30;
int* const ptr = &var1;
*ptr = 40; //valid,now var1=40
var1 = 50; //valid,now *ptr=50
ptr = &var2; //invalid
ptr = &var3; //invalid
//指向常量XX的指针常量
//不可以通过*ptr修改var1,var1本身也是常量,ptr不可以指向其他变量/常量
const int var1 = 10;
int var2 = 20;
const int var3 = 30;
const int* const ptr = &var1;
*ptr = 40; //invalid
var1 = 50; //invalid
ptr = &var2; //invalid
ptr = &var3; //invalid
3.2指针变量(指针类型的变量,即指针本身是一个变量)
int* ptr; //基数据类型* 指针变量名;强调ptr是一个指向int的指针(复合类型)
int *ptr; //基数据类型 *指针变量名;强调*ptr是一个int类型的值,常用于定义多个指针变量
//指向XX型变量的指针变量
//可以通过*ptr修改var1,*ptr也会随着var1的改变而改变,ptr可以指向其他变量,ptr不可以指向其他常量
int var1 = 10;
int var2 = 20;
const int var3 = 30;
int* ptr = &var1;
*ptr = 40; //valid,now var1=40
var1 = 50; //valid,now *ptr=50
ptr = &var2; //valid
ptr = &var3; //invalid
//指向XX型常量的指针变量
//不可以通过*ptr修改var1,var1本身也是常量,ptr可以指向其他变量/常量
const int var1 = 10;
int var2 = 20;
const int var3 = 30;
const int* ptr = &var1;
*ptr = 40; //invalid
var = 50; //invalid
ptr = &var2; //valid
ptr = &var3; //valid
3.3void* 类型指针
- 任何类型的指针都可以赋值给void*指针
- void*指针要赋值给其他类型的指针需要强制类型转换
- malloc得到的指针是void*类型
3.4NULL指针
- #define NULL ((void*)0)
- 当不清楚指针指向何处时,将其初始化为NULL
- 当对指针进行解引用时,判断其是否为NULL
3.5解引用操作符*
- 一定要先为指针变量赋值再使用
- *指针变量就是该指针指向的变量/常量
3.6从编译器角度
- 使用变量名是间接访问indirect access
- 使用指针是直接访问direct access
3.7指针运算
- 自加、自减,加/减常数
- 做差:ptrdiff_t diff=p2-p1; // 指针的减法可以计算两个指针之间相隔的元素个数,所得结果是一个 ptrdiff_t 类型
- 比较:== != > >= < <=
3.8指针与函数
- 指针变量作为函数参数,是使被调函数获得某变量的地址,从而使用这个地址访问这个变量
- 引用变量作为函数参数,形参和实参是同一个变量,形参是实参的别名
3.9指针与一维数组
- 数组名是指针常量,可以赋值给指针变量,此时指针变量可以代替数组名访问数组。二者均可用下标法:arr[i]和指针法:*(arr+i)
float score[5];
float* p = score;
float* p = &score[0];
- 数组作为函数参数时,形参是指针变量
foo( int arr[], int n)
foo( int* arr, int n)
- 指针本身并没有指出数组的长度,所以必要时还要增加参数传入数组的长度
- 对数组名使用sizeof运算符,得到的是数组的长度;对指针应用sizeof得到的是指针的长度,即使指针指向的是一个数组
short tell[10];
cout << tell << endl;
cout << &tell << endl;
cout << &tell + 1 << endl;
//两个输出地址相同,但是&tell[0](即tell)是一个2字节的内存块的地址,
//而&tell是一个20字节内存块的地址,所以tell+1将地址加2,而&tell+1是将地址加20;
3.10指针与二维数组
- 二维数组名是一个指向一维数组的指针常量,指向整个二维数组的地址,它的值正好等于一维数组arr[0],即第0行的地址
- 下标法arr[i][j],指针法*(*(arr+i)+j)
- 传递二维数组时,列数通过指针类型确定,如void print(int arr[][5],int row)
- 指向指针的指针
//type (*p)[col] 定义p为指向“由col个type型元素组成的一维数组”的指针
short (*p)[10] = &tell;
//pas指向包含10个元素的short数组
//pas的类型为short (*)[10]
//*pas与tell是等价的
int* arr[4]; //声明一个由4个指向int的指针组成的数组
int (*arr)[4]; //声明一个指向由4个int组成的数组的指针
//指针与二维数组
int arrt[2][3] = { {1,2,3},{4,5,6} };
cout << "arrt=" << arrt << endl; //二维数组名
cout << "arrt[0]=" << arrt[0] << endl; //第0行元素第0列的地址
cout << "*(arrt+0)=" << *(arrt + 0) << endl; //第0行元素第0列的地址
cout << "*arrt=" << *arrt << endl; //第0行元素第0列的地址
cout << "arrt+1=" << arrt + 1 << endl; //第一行的地址
cout << "&arrt[1]=" << &arrt[1] << endl; //第一行的地址
cout << "arrt[1]=" << arrt[1] << endl; //arr2[1][0]的地址
cout << "*(arrt+1)=" << *(arrt + 1) << endl; //arr2[1][0]的地址
cout << "arrt[1]+2=" << arrt[1] + 2 << endl; //arr2[1][2]的地址
cout << "*(arrt+1)+2=" << *(arrt + 1) + 2 << endl; //arr2[1][2]的地址
cout << "&arrt[1][2]=" << &arrt[1][2] << endl; //arr2[1][2]的地址
cout << "*(arrt[1]+2)=" << *(arrt[1] + 2) << endl; //arr2[1][2]
cout << "*(*(arrt+1)+2)=" << *(*(arrt + 1) + 2) << endl; //arr2[1][2]
cout << "arrt[1][2]=" << arrt[1][2] << endl; //arr2[1][2]
3.11创建动态数组
//malloc和free
指针变量 = (type*)malloc(sizeof(type)*length);
free(指针变量);
//new和delete
type* arr; //一维数组
arr = new type[length];
delete[]arr;
type **arr; //二维数组
arr = new type*[col];
for (i = 0; i < col; i++)
arr[i] = new type[row];
for (int i = 0; i < col; i++)
delete[]arr[i];
delete[]arr;
3.12指针与结构
structname* pointer = &a_struct;
pointer->member == (*pointer).member == a_struct.member;
structname* pointer = new structname;
delete pointer;
3.13指针与对象
classname *pointer = &object;
pointer->member = (*pointer).member = object.member;
classname *pointer = new classname(arguments);
delete pointer;
3.14传递指针给函数
3.15从函数返回指针
3.16函数指针
- !=返回指针的函数
- type *函数名(形参列表);返回指向type型的指针
- 函数名是一个指针常量,可以赋给指针变量,然后指针变量可以代替函数名被调用
- type (*指针变量)(形参列表);type就是指针变量要指向的函数的返回值类型,形参列表也要和指针变量指向的函数的形参列表一致,可以没有形参名字
- 实现晚绑定
bool min(int a,int b);
bool (*p)(int,int);
p = min;
p(3,4) = (*p)(3,4) = min(3,4);
typedef bool (*ptr)(int,int);
ptr p1 = min;