【 数组与指针 】
1. 指向整型变量的指针
指针变量,表示指向某变量地址的变量,即内存所指向变量的地址。Eg. int a = 1; int *p = &a; => *p = 1;
p和*p的值都是可以改变的(在没有const修饰的情况下):
p的值该表表示p指向了其他元素,而*p的值改变,表示*p指向的元素的值改变(要先给p赋值才可以给*p赋值,否则p指向未知的地址)
2. 指向一维整型数组的指针
对于一个数组而言,数组名可看做指向数组起始位置的指针:
假设我们有一组数组, int a[5] = {1,2,3,4,5}, 我们有:
a == &a[0]; a+i == &a[i], *(a+i) == a[i]
由此可以把a赋值给一个整型指针,并通过该指针访问数组:
int *p = a; =>
p+i == a+i == &a[i] => *(p+i) == a[i]
可以通过p++来遍历整个数组,效率会比数组名遍历高。
3. 指向多维整形数组的指针
对于多维数组,我们可以通过下图来理解;假设有二维数组: int a[2][3] = {{1,2,3}, {4,5,6}};
一维数组数组名可看做指向该数组第一个元素的起始地址;
二维数组数组名可看做指向该数组行维度里的第一个元素(即第一行)的起始地址;
a: &a[0] 第0行起始位置;
a+i: &a[i] 第i行起始位置;
*(a+i): a[i] 第i行第0个元素起始位置;
*(a+i)+j: a[i]+j 第i行第j个元素起始位置;
*(*(a+i)+j): a[i][j] 第i行第j个元素起始位置
可以定义一个指向该多维数组某行的指针:int (*p)[3] = a+i; p指向第i行起始位置, p++操作可指向数组下一行起始位置,
*p表示a[i], *p+j, 表示第i行第j个元素起始位置
注意需要括号 (*p), 表示是一个指向有3个int元素数组的指针;
若写成 int *p[3], 则表示有3个元素的整型指针数组;
4. 字符数组
字符数组是比较特殊的一类数组,可以用来表示一个字符串
char str[] = {"I love C++"};
也可定义为: char *str2 = "I love C++"; (*str2 == str[0] == 'I', str2 == str == "I love C++")
如果是定义一个二维字符数组,一般可用一个指针数组定义:
char *str[] = { {"I"}, {"love"}, {"C++"}};
str[0] = "I", str[1] = "love", str[2] = "C++"
之所以用指针数组来定义二维字符数组,因为一般情况下这样的数组列数不一致无法确定长度。
5. 指向指针的指针
指向指针的指针,常用来定义一个指针数组:
int **p1 => int *p2[ ]; (p2是一个指针数组数组名,指向该数组第一个指针的起始地址)
char **str1 => char *str2[ ];
=> p1 = p2: p1+i == p2+i == &p2[i] (数组中第i个指针的地址); *(p1+i) == *(p2+i) == p2[i](第i个指针,即第i个指针指向的元素地址);
**(p1+i) == **(p2+i) == *p2[i] (数组中第i个指针指向的数值)
=> str1 = str2: str1+i == str2+i == &(str2[i]) (数组中第i个指针的地址); *(str1+i) == *(str2+i)==str2[i](第i个指针,即第i个字符串);
**(str1+i) == **(str2+i) == *str2[i] (数组中第i个指针指向的字符串的第一个字符)
【区分】
二维数组数组名 => 对应指向二维数组某行的指针; int a1[3][4] => int (*p1)[4]
一维指针数组名 => 对应指向指针的指针; int *a2[4] => int **p2
指针值 | 对应数组值 | 表示 |
p1 | a1/&a1[0] | 第0行起始地址 |
p2 | a2/&a1[0] | 第0个指针起始地址 |
p1+i | a1+i/&a1[i] | 第i行起始地址 |
p2+i | a2+i/&a1[i] | 第i个指针起始地址 |
*(p1+i) | *(a1+i)/a1[i] | 第i行第0个元素起始地址 |
*(p2+i) | *(a2+i)/a2[i] | 第i个指针值,第i个指针指向的元素的起始地址 若为字符类型,也可表示第i个字符串 |
*(p1+i)+j | *(a1+i)+j/&a1[i][j] | 第i行第j个元素起始地址 |
*(p2+i)+j | NA | NA |
*(*(p1+i)+j) | *(*(a1+i)+j)/a[i][j] | 第i行第j个元素的值 |
*(*(p2+i)+j) | NA | |
**p2 | **a2/*a2[0] | 第0个指针指向的元素的值 |
**(p2+i) | **(a2+i)/*a2[i] | 第i个指针指向的元素的值 |
**p1/**(p1+i) | NA |
代码示例:
#include <iostream> using namespace std; int main() { int a1[3][4] = {{1,2,3,4}, {5,6,7,8}, {9,10,11,12}}; int *a2[4]; for(int i = 0; i < 4; ++i) a2[i] = &a1[0][i]; int (*p1)[4] = a1; int **p2 = a2; cout << *(*(p1+1)+2) << ", " << a1[1][2] << endl; //第1行第2列元素的值 cout << **(p2+1) << ", " << *a2[1] << endl; //第1个指针指向的元素的值 char *str[] = {"Hello", "World", "I", "Love", "C++"}; char **sp = str; cout << *(sp+1) << ", " << str[1] << endl; //第1个字符串 cout << **(sp+1) << ", " << *str[1] << endl; //第1个字符串的第0个字符 }
输出结果:
7, 7 2, 2 World, World W, W
【 指向函数的指针 】
int (*p)(int, int): 表示指针p是一个可以指向函数原型为 int func(int a, int b)一类的函数,为简化代码以及提高代码可维护性。
当给p赋值: p = func, p指向函数func的入口处;可通过p来调用指针func
#include <iostream> using namespace std; int minNum(int a, int b) { return (a < b)?a:b; } int maxNum(int a, int b) { return (a > b)?a:b; } int main() { int x = 3, y = 5; int (*p)(int, int); p = maxNum; cout << "The bigger number of " << x << " and " << y << " is: " << p(x, y) << endl; p = minNum; cout << "The smaller number of " << x << " and " << y << " is: " << p(x, y) << endl; }
输出:
The bigger number of 3 and 5 is: 5 The smaller number of 3 and 5 is: 3