本博客采用创作共用版权协议, 要求署名、非商业用途和保持一致. 转载本博客文章必须也遵循署名-非商业用途-保持一致的创作共用协议.

指针

  • 高级语言中的变量是使用户以一种简单的方式记住内存地址, 硬件依然是通过地址访问内存位置
  • 如何判断地址中存储变量类型是通过访问时使用的机器指令
  • 指针存储内存地址, 通过指针访问指针所指向的内存地址的过程称为间接访问
  • 指针和一个整数量执行算术运算时, 整数在执行加法/减法前始终根据合适的大小调整(int型指针加一操作实际上内存地址+4, int占四个字节)

动态内存分配问题:

当指针指向一块已经分配内存的变量时, 无需malloc分配动态内存. 当想通过指针使用一块内存存储数据时, 需要动态开辟内存.

传参问题:

  • 如果不想修改指针, 指向修改指针中内存的值的时候, 不需要再加一重指针
  • 如果需要修改指针中存储的内存地址时, 需要在原基础上增加一重指针
1
2
3
4
ListNode* root; //链表的根节点
bool FindValue(ListNode* root, int value); //从链表中查找某个值是否存在. 无需修改root内存储的地址.
bool InsertValue(ListNode** root, int value); //将一个值插入某有序链表. 此函数可能使插入的节点变为新的头结点, 此时需要修改root, 所以需要使用二重指针使函数外部同步修改.

函数指针

函数指针的初始化, 其中&是可选的, 函数名被使用时总是被编译器转换成函数指针, 指针指向函数在内存中的位置

1
2
3
int f(int); //函数原型
int (*pf)(int) = &f;
int (*pf)(int) = f; //等价
1
2
// 函数指针数组
int* (*fun[])(float left, int right); //合法声明一个函数指针数组, 接受两个参数并返回int型指针

数组

数组名的值是一个指针常量(无法修改), 即数组第一个元素的地址. 数组名的类型是指向数组类型的常量指针

1
2
3
4
5
6
7
8
// 声明一个数组
int nums[20];
// 声明一个函数原型
void ClearArray(int array[], int len);
void ClearArray(int* array, int len); //等价
//调用函数, 数组名为数组第一个元素的地址, 所以此处为传址调用
void ClearArray(nums, 20);

数组和指针的区别:

  • 声明数组时, 编译器将根据声明所指定的元素数量为数组保留内存空间, 然后再创建数组名, 他的值是一个常量, 并指向这段空间的起始位置
  • 声明指针时, 编译器只为指针本身保留内存空间
1
2
3
4
// 字符数组
char message[] = "Hello";
// 字符串常量
char* str = "Hello"; //指针常量

指向数组的指针

  • 下标实际上是间接访问数组的一种伪装形式, 其等价于指针解引用访问
1
2
3
4
5
6
7
8
9
// 二维数组的下标和指针表示第二行第六个元素, 二者等价
matrix[1][5];
*(*(matrix + 1) + 5);
// 指向数组的指针
int vector[10], *pvector = vector;
int matrix[3][10];
int (*p)[10] = matrix; // p是一个指向整型数组的指针, 定义 类型说明符 (*指针变量名)[长度]
*(*(p + 1) +5); // 指针访问第二行第六个元素

二维数组传参

传递给函数的数组是一份拷贝(指向数组其实位置的指针的拷贝), 所以C语言中所有参数都是传值调用

  • 动态分配内存需要检测内存是否分配成功
  • 防止超过已分配内存边界
1
2
3
4
5
6
7
// 一维数组, 使用指向整型的指针
int vector[10];
void func(int* matrix); // 等价于void func(int matrix[]);
//二维数组, 使用指向整型数组的指针(必须有第二维的长度)
int matrix[3][10];
void func(int (*mat)[10]); // 等价于void func(int mat[][10]);

指针数组

不同于指向数组的指针, 指针数组是一个由指针组成的数组.(下标操纵优先级高于解引用)

动态二维数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 动态二维数组
int main(int argc, char** argv) {
int row, line;
while(cin >> row >> line) {
int** matrix = new int*[row];
for(int i = 0; i < row; i++)
matrix[i] = new int[line];
for(int i = 0; i < row; i++) {
for (int j = 0; j < line; j++) {
cin >> matrix[i][j];
}
}
for(int i = 0; i < row; i++)
delete [] matrix[i];
delete [] matrix;
}
}

参考链接