1. 指针overview
1.1 what is 指针
指针 is a特殊 variable, 它store is memory地址, 而不 is 普通 值. in Clanguagein, 指针 is a非常 important concepts, 它providing了直接访问memory capacity, 使得程序可以更flexible, 更 high 效地operationdata.
指针 主要用途including:
- 直接访问memory地址
- 动态分配memory
- implementationfunction间 data传递 (through引用)
- operationarray and string
- implementation complex datastructure (such as链表, tree, graphetc.)
1.2 memory地址 concepts
in 计算机in, memory被划分 for 一个个连续 store单元, 每个store单元都 has 一个唯一 地址. memory地址通常用十六进制数表示, 例such as0x1000.
当我们声明一个variable时, 编译器会 for 该variable分配一定 big small memory空间, 并将该memory空间 地址 and variable名关联起来. 例such as:
int num = 10; // 编译器 for num分配4个字节 memory空间, 并将值10store in 该空间in
2. 指针 声明 and 初始化
2.1 指针 声明
in Clanguagein, 声明指针 basic语法such as under :
dataclass型 *指针variable名; // example int *p; // 声明一个指向整数 指针 float *fp; // 声明一个指向浮点数 指针 char *cp; // 声明一个指向字符 指针
注意: *号表示这 is a 指针variable, 而不 is 普通variable. 指针variable class型必须 and 它所指向 variable class型一致.
2.2 指针 初始化
指针variable in 声明 after 需要初始化, 否则它会指向一个随机 memory地址 (野指针) . 指针 初始化 has 两种方式:
2.2.1 using取地址运算符(&)
int num = 10; int *p = # // 将指针p初始化 for variablenum 地址
2.2.2 usingNULL初始化
int *p = NULL; // 将指针p初始化 for 空指针
NULL is a 特殊 常量, 表示空指针, 它 值 for 0. 空指针不指向任何 has 效 memory地址.
2.3 指针 big small
in Clanguagein, 指针 big small 取决于编译器 and operationsystem 位数, 而不 is 它所指向 dataclass型 big small . in 32位systemin, 指针 big small 通常 is 4字节; in 64位systemin, 指针 big small 通常 is 8字节.
#include <stdio.h>
int main() {
int *p;
float *fp;
char *cp;
printf("int指针 big small : %d字节\n", sizeof(p));
printf("float指针 big small : %d字节\n", sizeof(fp));
printf("char指针 big small : %d字节\n", sizeof(cp));
return 0;
}
run结果 ( in 64位system on ) :
int指针 big small : 8字节 float指针 big small : 8字节 char指针 big small : 8字节
3. 指针 basicoperation
3.1 取地址运算符(&)
取地址运算符&用于获取variable memory地址. 例such as:
#include <stdio.h>
int main() {
int num = 10;
printf("num 值: %d\n", num);
printf("num 地址: %p\n", &num);
return 0;
}
run结果:
num 值: 10 num 地址: 0x7ffe5b7d8a4c
3.2 解引用运算符(*)
解引用运算符*用于获取指针所指向 memory地址instore 值. 例such as:
#include <stdio.h>
int main() {
int num = 10;
int *p = #
printf("num 值: %d\n", num);
printf("p 值 (num 地址) : %p\n", p);
printf("*p 值 (p所指向 in 容) : %d\n", *p);
return 0;
}
run结果:
num 值: 10 p 值 (num 地址) : 0x7ffe5b7d8a4c *p 值 (p所指向 in 容) : 10
3.3 modify指针所指向 值
through解引用运算符, 我们可以modify指针所指向 memory地址instore 值:
#include <stdio.h>
int main() {
int num = 10;
int *p = #
printf("modify before , num 值: %d\n", num);
printf("modify before , *p 值: %d\n", *p);
// through指针modifynum 值
*p = 20;
printf("modify after , num 值: %d\n", num);
printf("modify after , *p 值: %d\n", *p);
return 0;
}
run结果:
modify before , num 值: 10 modify before , *p 值: 10 modify after , num 值: 20 modify after , *p 值: 20
3.4 指针 算术运算
指针可以for算术运算, including加法, 减法 and 比较运算. 但指针 算术运算 and 普通variable 算术运算 has 所不同, 指针 算术运算practical on is in memory地址 on 运算.
3.4.1 指针 加法
#include <stdio.h>
int main() {
int arr[] = {10, 20, 30, 40, 50};
int *p = arr; // array名就 is array 首地址
printf("p指向 地址: %p, 值: %d\n", p, *p);
// 指针加1, 指向array under 一个元素
p++;
printf("p+1指向 地址: %p, 值: %d\n", p, *p);
// 指针加2, 指向array 第三个元素
p += 2;
printf("p+2指向 地址: %p, 值: %d\n", p, *p);
return 0;
}
run结果:
p指向 地址: 0x7ffe5b7d8a40, 值: 10 p+1指向 地址: 0x7ffe5b7d8a44, 值: 20 p+2指向 地址: 0x7ffe5b7d8a4c, 值: 40
注意: 指针加1, practical on is 增加了一个所指向class型 big small 字节数. 例such as, intclass型 指针加1, 地址增加4字节 ( in 32位system on ) .
4. 指针 and array
4.1 array名 and 指针 relationships
in Clanguagein, array名practical on is a 指向array首元素 常量指针. 例such as:
#include <stdio.h>
int main() {
int arr[] = {10, 20, 30, 40, 50};
printf("array名arr 值: %p\n", arr);
printf("array首元素 地址: %p\n", &arr[0]);
printf("array首元素 值: %d\n", *arr);
return 0;
}
run结果:
array名arr 值: 0x7ffe5b7d8a40 array首元素 地址: 0x7ffe5b7d8a40 array首元素 值: 10
4.2 through指针访问array元素
由于array名 is a 指向array首元素 指针, 我们可以through指针来访问array 所 has 元素:
#include <stdio.h>
int main() {
int arr[] = {10, 20, 30, 40, 50};
int *p = arr;
int i;
printf("through指针访问array元素: ");
for (i = 0; i < 5; i++) {
printf("%d ", *(p + i));
}
printf("\n");
return 0;
}
run结果:
through指针访问array元素: 10 20 30 40 50
4.3 指针 and many 维array
for 于 many 维array, 我们可以using指针来访问其元素. 例such as, for 于二维array:
#include <stdio.h>
int main() {
int arr[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
int (*p)[4] = arr; // 指向package含4个整数 array 指针
int i, j;
printf("through指针访问二维array元素:\n");
for (i = 0; i < 3; i++) {
for (j = 0; j < 4; j++) {
printf("%d ", *(*(p + i) + j));
}
printf("\n");
}
return 0;
}
run结果:
through指针访问二维array元素: 1 2 3 4 5 6 7 8 9 10 11 12
5. 指针 and function
5.1 指针serving asfunctionparameter
指针可以serving asfunctionparameter, 这样function就可以modify实参 值 (through引用传递) . 例such as:
#include <stdio.h>
// 交换两个整数 值
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
int main() {
int x = 10, y = 20;
printf("交换 before : x = %d, y = %d\n", x, y);
// 传递x and y 地址
swap(&x, &y);
printf("交换 after : x = %d, y = %d\n", x, y);
return 0;
}
run结果:
交换 before : x = 10, y = 20 交换 after : x = 20, y = 10
5.2 返回指针 function
function可以返回指针, 这样function就可以返回一个memory地址. 例such as:
#include <stdio.h>
// 返回两个整数in较 big 值 地址
int *max(int *a, int *b) {
if (*a > *b) {
return a;
} else {
return b;
}
}
int main() {
int x = 10, y = 20;
int *p;
p = max(&x, &y);
printf("较 big 值: %d\n", *p);
return 0;
}
run结果:
较 big 值: 20
注意: function不应该返回局部variable 地址, 因 for 局部variable in function执行结束 after 会被销毁, 其memory地址会被释放.
6. 指针 advancedapplication
6.1 many 级指针
many 级指针 is 指向指针 指针. 例such as, 二级指针 is 指向指针variable 指针:
#include <stdio.h>
int main() {
int num = 10;
int *p = # // 一级指针, 指向num
int **pp = &p; // 二级指针, 指向p
printf("num 值: %d\n", num);
printf("p 值 (num 地址) : %p\n", p);
printf("*p 值 (p所指向 in 容) : %d\n", *p);
printf("pp 值 (p 地址) : %p\n", pp);
printf("*pp 值 (pp所指向 in 容, 即p 值) : %p\n", *pp);
printf("**pp 值 (*pp所指向 in 容, 即num 值) : %d\n", **pp);
return 0;
}
run结果:
num 值: 10 p 值 (num 地址) : 0x7ffe5b7d8a4c *p 值 (p所指向 in 容) : 10 pp 值 (p 地址) : 0x7ffe5b7d8a50 *pp 值 (pp所指向 in 容, 即p 值) : 0x7ffe5b7d8a4c **pp 值 (*pp所指向 in 容, 即num 值) : 10
6.2 function指针
function指针 is 指向function 指针, 它store is function 地址. function指针可以用来调用function, 也可以serving asfunctionparameter传递给otherfunction.
#include <stdio.h>
// 加法function
int add(int a, int b) {
return a + b;
}
// 减法function
int subtract(int a, int b) {
return a - b;
}
// function指针serving asparameter
int calculate(int (*operation)(int, int), int a, int b) {
return operation(a, b);
}
int main() {
int (*func_ptr)(int, int); // 声明一个function指针
int result;
// 指向加法function
func_ptr = add;
result = func_ptr(10, 5);
printf("10 + 5 = %d\n", result);
// 指向减法function
func_ptr = subtract;
result = func_ptr(10, 5);
printf("10 - 5 = %d\n", result);
// usingfunction指针serving asparameter
result = calculate(add, 20, 10);
printf("20 + 10 = %d\n", result);
result = calculate(subtract, 20, 10);
printf("20 - 10 = %d\n", result);
return 0;
}
run结果:
10 + 5 = 15 10 - 5 = 5 20 + 10 = 30 20 - 10 = 10
7. 指针 Notes
7.1 空指针
空指针 is 指向NULL 指针, 它不指向任何 has 效 memory地址. in using指针之 before , 应该check它 is 否 for 空:
#include <stdio.h>
int main() {
int *p = NULL;
// check指针 is 否 for 空
if (p == NULL) {
printf("指针p is 空指针\n");
} else {
printf("*p = %d\n", *p);
}
return 0;
}
7.2 野指针
野指针 is 指向无效memory地址 指针, 它通常 is 由于以 under 原因造成 :
- 指针variable未初始化
- 指针指向 memory已被释放
- 指针越界访问
using野指针 is 非常 dangerous , 可能会导致程序崩溃 or data损 bad . for 了避免野指针, 我们应该:
- 始终初始化指针variable
- in 指针指向 memory被释放 after , 将指针设置 for NULL
- 避免指针越界访问
7.3 指针 securityusing
#include <stdio.h>
#include <stdlib.h>
int main() {
int *p = NULL; // 初始化指针 for NULL
// 动态分配memory
p = (int *)malloc(sizeof(int));
// checkmemory分配 is 否成功
if (p == NULL) {
printf("memory分配失败\n");
return 1;
}
// using指针
*p = 10;
printf("*p = %d\n", *p);
// 释放memory
free(p);
// 将指针设置 for NULL, 避免野指针
p = NULL;
return 0;
}
实践case: using指针implementationstring反转
writing一个C程序, using指针implementationstring反转functions.
requirementsanalysis
- 输入一个string
- using指针implementationstring反转
- 输出反转 after string
referencecode
#include <stdio.h>
#include <string.h>
// using指针反转string
void reverse_string(char *str) {
char *start = str;
char *end = str + strlen(str) - 1;
char temp;
while (start < end) {
// 交换两个字符
temp = *start;
*start = *end;
*end = temp;
// move指针
start++;
end--;
}
}
int main() {
char str[100];
// 输入string
printf("请输入一个string: ");
scanf("%s", str);
// 反转string
reverse_string(str);
// 输出反转 after string
printf("反转 after string: %s\n", str);
return 0;
}
run结果
请输入一个string: hello 反转 after string: olleh
互动练习
练习1: writing一个C程序, using指针计算array and and 平均值.
提示: using指针遍历array, 计算所 has 元素 and , 然 after 计算平均值.
练习2: writing一个C程序, using指针implementation两个string 连接.
提示: using指针找 to 第一个string 末尾, 然 after 将第二个string 字符copy to 第一个string 末尾.
练习3: writing一个C程序, usingfunction指针implementation一个 simple 计算器.
提示: 定义加法, 减法, 乘法, 除法function, usingfunction指针arraystore这些function 地址, 根据user输入选择相应 function.