本课有B站视频讲解 link
0x001 | 0x002 | 0x003 | 0x004 | 0x005 | ..... | 0xFFF |
---|---|---|---|---|---|---|
低地址 | > | > | > | > | > | 高地址 |
用 &
获取变量在内存中的首地址
grammar
&变量名
-
指针的定义和使用 建议形式:
基类型* 变量名 = 变量地址;
- 指针要赋初值
int a = 10; int* p = &a;
int* p
int * p
int *p
int*p
都表示定义指针 但是请按照建议形式定义 - 多个指针可以指向一个地址
int *p1 = &a; int* p2 = &a; int* p3 = &a;
- 指针类型可以强制转换
double a = 20.0; int* p = (double*)&a;
- 指针占用内存
所有变量类型的指针占用内存在64位系统中都为8,32位系统中位4
int lengthInt = sizeof(int*); int lengthDouble = sizeof(double*); int lengthChar = sizeof(char*); int lengthBool = sizeof(bool*);
- 解引用
*
运算符的优先级较低,注意加括号int a = 10; int* p = &a; printf("%d", *p); // 10
- 指针要赋初值
-
空指针和野指针
空指针:指针变量指向内存中编号为0的空间#define NULL ((void *)0)
可用于初始化指针变量 但是空指针指向的内存是不可以访问的
int* p = NULL;
野指针:指针变量指向非法的内存空间
0-255内存编号是系统占用的,不可以访问
在程序中尽量避免出现野指针int* p = 0x001; // error
-
const
修饰指针- 指针常量
指针为常量
指针不可修改
int a = 10; int b = 10; int* const p = &a; *p = 10; p = &b; // error
- 常量指针
指向常量的指针
指针指向的值不可修改
int a = 10; int b = 10; const int* p = &a; // or int const* p = &a; *p = 10; // error p = &b;
- 常指针常量
指针地址和指向的值都不可修改
int a = 10; int b = 10; const int* const p = &a; *p = 10; // error p = &b; // error
- 指针常量
指针为常量
指针不可修改
-
地址传递 可以改变形参的值
void swap(int* a, int* b) { // 对解引用值进行操作 而不是对指针变量进行操作 int tmp = *a; *a = *b; *b = tmp; } int main() { int a = 10; int b = 20; swap(&a, &b); printf("a = %d, b = %d", a, b); // a = 20, b = 10 }
-
指针作为形参返回多个值
void add(int* a, int* b) { (*a)++; (*b)++; } int main() { int a = 10; int b = 10; add(&a, &b); printf("a = %d, b = %d", a, b); // a = 11, b = 21 return 0; }
-
void
关键字只关心地址本身,不关心里面内容,用
void*
可以存放任意类型的地址void function(void* p) { printf("the var's address is %p\n", p); } int main() { int a = 10; function(&a); // the var's address is 0x..... return 0; }
note:
- 不能用
void
声明变量 - 不能对
void*
直接解引用,需要转换成其他类型指针 - 把其他类型指针赋值给
void*
指针不需要转换 - 把
void*
指针赋值给其他指针需要转换
- 不能用
-
返回指针的函数
int* function(int* a) {return a}
int* function(int a){ int* p = &a; return p; }
-
函数指针
返回值类型 (*指针变量名) (参数表);
void function(int x) { printf("%d", x); } int main(){ int (*pFunction) (int x); pFunction = function; // pFunction指向function *pFunction(10); // 10 }
-
回调函数
-
一维数组 数组名为数组首地址 是一个指针常量
数组元素地址表示 数组 arr[5]
数组元素表示 arr
or&arr[0]
arr[0]
arr[0]
or*arr
arr + 1
or&arr[1]
arr[1]
arr[1]
or*(arr + 1)
arr + 2
or&arr[2]
arr[2]
arr[2]
or*(arr + 2)
arr + 3
or&arr[3]
arr[3]
arr[3]
or*(arr + 3)
arr + 4
or&arr[4]
arr[4]
arr[4]
or*(arr + 4)
数组相邻元素地址差值 = 基类型占用内存大小 -
二维数组
-
二维数组
a[2][3]
在内存中的存储形式a[0][0]
a[0][1]
a[0][2]
a[1][0]
a[1][1]
a[1][2]
-
二维数组
a[2][3]
直观表示0 1 2 0 a[0][0]
a[0][1]
a[0][2]
1 a[1][0]
a[1][1]
a[1][2]
-
-
二维数组的本质是行指针数组
arr
↓arr[0] -> arr[0][0] arr[0][1] arr[0][2] arr[1] -> arr[1][0] arr[1][1] arr[1][2] -
指针数组
变量类型* 指针变量名[数组长度]
int a[3][2]; int* p[3]; for(int i = 0; i < 3; i++){ p[i] = a[i]; }
数组地址 p[3]
数组元素指针指向 p
p[0] = a[0]
a[0][0]
&p[1]
orp + 1
p[1] = a[1]
a[1][0]
&p[2]
orp + 2
p[2] = a[2]
a[2][0]
数组相邻元素地址差值 = 指针占用内存大小
###5. 指针&数组&函数
-
一维数组和函数
int a[10]; // 两种写法等价 void func(int* a); void func(int a[]);
-
行指针 / 数组指针
变量类型 (*指针变量名)[每行长度]
int a[3][2]; int (*p)[2]; p = a;
数组地址 (*p)[3]
数组元素指针指向 p
a[0]
a[0][0]
&p[1]
orp + 1
a[1]
a[1][0]
&p[2]
orp + 2
a[2]
a[2][0]
数组相邻元素地址差值 = 基类型占用内存大小,即一维数组所占内存
-
行指针指向一定长度的数组首地址 类型为
void[]*
,基类型为void[][]
-
行指针解决二维数组传参
//两种写法等价 void func(int (*p)[2]); void func(int p[][2]);
-
- 指针访问一维数组
void for_each(int arr[], int len) {
for (int i = 0; i < len; i++) {
printf("%d ", *(arr + i));
//or
printf("%d ", arr[i]);
}
}
int main() {
int a[5] = {1, 2, 3, 4, 5};
int len = sizeof(a) / sizeof(int);
for_each(a, len);
return 0;
}
- 指针数组访问二维数组
int main() {
int a[3][2] = {1, 2, 3, 4, 5, 6};
int* p[3];
for (int i = 0; i < 3; i++) {
p[i] = a[i];
for (int j = 0; j < 2; j++) {
printf("%d", *(p[i] + j));
}
printf("\n");
}
return 0;
}
- 行指针访问二维数组
int main() {
int a[3][2] = {1, 2, 3, 4, 5, 6};
int(*p)[2];
p = a; // 行指针p等价与二维数组名a
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 2; j++) {
printf("%d", *(p[i] + j));
// or
printf("%d", p[i][j]);
}
printf("\n");
}
return 0;
}
- 行指针解决二维数组传参
void for_each(int arr[][2], int len) {
for (int i = 0; i < 2; i++) {
for (int j = 0; j < len; j++) {
printf("%d", *(arr[i] + j));
// or
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
int main() {
int a[3][2] = {1, 2, 3, 4, 5, 6};
int len = sizeof(a) / sizeof(int[2]);
for_each(a, len);
return 0;
}
void function(int arr[], int len, int* max, int* min) {
for (int i = 0; i < len; i++) {
if (*(arr + i) > *max) {
*max = *(arr + i);
}
}
for (int i = 0; i < len; i++) {
if (*(arr + i) <= *min) {
*min = *(arr + i);
}
}
}
int main() {
int a[5] = {300, 350, 200, 400, 250};
int len = sizeof(a) / sizeof(int);
int max = 0, min = 1000;
function(a, len, &max, &min);
printf("%d %d", max, min);
return 0;
}
void bubbleSort(int* arr, int len) {
for (int i = 0; i < len - 1; i++) {
for (int j = 0; j < len - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}
void printArr(int arr[], int len) {
for (int i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
int main() {
int a[5] = {300, 350, 200, 400, 250};
int len = sizeof(a) / sizeof(int);
bubbleSort(a, len);
printArr(a, len);
return 0;
}