[C.C++] 「C系列」C 指针及其应用案例

60 0
Honkers 昨天 18:18 来自手机 | 显示全部楼层 |阅读模式


一、C 指针

在C语言中,指针是一个非常重要的概念,它允许程序直接访问内存地址,并操作该地址上存储的数据。指针本身是一个变量,但它存储的不是实际的数据值,而是存储数据值的内存地址。

以下是关于C语言中指针的一些基本概念和用法:

1. 指针的定义

指针变量通常通过以下方式定义:

  1. int *ptr; // 定义一个指向int类型数据的指针变量ptr
复制代码

这里的int *是一个类型,表示这是一个指向int类型数据的指针。

2. 指针的初始化

在定义指针变量后,通常需要将其初始化为一个有效的内存地址。这可以通过以下方式完成:

  1. int x = 10;
  2. int *ptr = &x; // 将ptr初始化为x的地址
复制代码

在这里,&是一个取地址运算符,它返回变量x在内存中的地址。

3. 指针的解引用

解引用指针意味着访问指针所指向的内存地址上的数据。这可以通过在指针变量前加*来实现:

  1. int y = *ptr; // 将ptr所指向的int值(即x的值)赋值给y
复制代码

4. 指针的运算

指针可以进行一些基本的算术运算,如加法、减法等。但这些运算不是基于指针的值(即内存地址),而是基于指针所指向的数据类型的大小。例如,如果ptr是一个指向int的指针,那么ptr + 1将指向下一个int类型的内存位置。

5. 动态内存分配

在C语言中,可以使用malloc和calloc等函数在运行时动态地分配内存,并将返回的内存地址存储在指针变量中。例如:

  1. int *array = (int *)malloc(10 * sizeof(int)); // 分配一个包含10个int的数组的内存
复制代码

注意:在使用完动态分配的内存后,应使用free函数释放内存,以避免内存泄漏。

6. 指针的NULL初始化

为了避免野指针(指向无效内存地址的指针),通常会将指针初始化为NULL:

  1. int *ptr = NULL;
复制代码

7. 指针作为函数参数和返回值

指针经常作为函数的参数和返回值,以实现数据的间接访问和修改。例如,一个交换两个整数值的函数可以接收两个指向整数的指针作为参数:

  1. void swap(int *a, int *b) {
  2. int temp = *a;
  3. *a = *b;
  4. *b = temp;
  5. }
复制代码

8. 指针数组和数组指针

  • 指针数组:一个数组,其元素是指针。
  • 数组指针:一个指针,指向数组的首个元素。

这两者在语法和用途上有所不同,需要仔细区分。

9. 多级指针

在C语言中,还可以定义指向指针的指针,即多级指针。例如,int **ptr是一个指向int指针的指针。多级指针在某些复杂的数据结构和算法中非常有用。

二、C语言中有哪些内置的指针操作符

在C语言中,与指针相关的内置操作符主要有以下几个:

  1. 取地址操作符(&)
  • 这个操作符用于获取变量的内存地址。
  • 示例:int x = 10; int *ptr = &x; 这里,&x 就是取变量 x 的地址,并将这个地址赋值给指针 ptr。
  1. 解引用操作符(*)
  • 这个操作符用于访问指针所指向的内存地址中的数据。
  • 示例:int y = *ptr; 这里,*ptr 就是访问 ptr 所指向的内存地址上的数据,并将其赋值给变量 y。
  • 当 * 出现在声明中时,它表示指针的类型;但在表达式中,它表示解引用操作。
  1. 指针算术操作符(+ 和 -)
  • 这两个操作符用于指针的算术运算。
  • 当用于指针时,它们基于指针所指向的数据类型的大小进行运算。例如,对于指向 int 的指针,ptr + 1 会将指针向前移动一个 int 的大小。
  • 示例:ptr++ 和 ptr += 2 等都是有效的指针算术操作。
  1. 指针比较操作符(==、!=、<、<=、>、>=)
  • 这些操作符用于比较两个指针是否指向相同的内存地址,或者它们在内存中的相对位置。
  • 需要注意的是,只有当两个指针指向同一数组(或同一块内存区域)中的元素时,比较它们的大小才有意义。
  1. -> 操作符(结构体指针的成员访问)
  • 这个操作符用于通过结构体指针访问结构体的成员。
  • 示例:如果 struct_ptr 是一个指向结构体的指针,并且该结构体有一个名为 member 的成员,则可以使用 struct_ptr->member 来访问这个成员。
  1. . 操作符(结构体的成员访问)
  • 虽然这不是一个专门的指针操作符,但在与结构体和指针一起使用时,. 操作符用于通过结构体变量访问其成员。
  • 示例:如果 struct_var 是一个结构体变量,并且该结构体有一个名为 member 的成员,则可以使用 struct_var.member 来访问这个成员。

需要注意的是,除了上述操作符之外,还有其他一些操作符(如赋值操作符 =、自增/自减操作符 ++ 和 -- 等)也可以与指针一起使用,但它们并不是专门为指针设计的。

三、常见应用案例

C 语言中的指针具有广泛的应用,以下是一些常见的应用案例及其详细代码:

1. 交换两个变量的值

使用指针可以避免使用临时变量来交换两个变量的值。

  1. #include <stdio.h>
  2. void swap(int *a, int *b) {
  3. int temp = *a;
  4. *a = *b;
  5. *b = temp;
  6. }
  7. int main() {
  8. int x = 5, y = 10;
  9. printf("Before swap: x = %d, y = %d\n", x, y);
  10. swap(&x, &y);
  11. printf("After swap: x = %d, y = %d\n", x, y);
  12. return 0;
  13. }
复制代码

2. 数组与指针

在 C 语言中,数组名实际上是一个指向数组首元素的指针。

  1. #include <stdio.h>
  2. void printArray(int *arr, int size) {
  3. for (int i = 0; i < size; i++) {
  4. printf("%d ", arr[i]); // 也可以使用 *(arr + i)
  5. }
  6. printf("\n");
  7. }
  8. int main() {
  9. int arr[] = {1, 2, 3, 4, 5};
  10. int size = sizeof(arr) / sizeof(arr[0]);
  11. printArray(arr, size);
  12. return 0;
  13. }
复制代码

3. 字符串操作

在 C 语言中,字符串是通过字符数组实现的,而字符串操作经常涉及到指针。

  1. #include <stdio.h>
  2. #include <string.h>
  3. void concat(char *dest, const char *src) {
  4. while (*dest) { // 找到 dest 字符串的末尾
  5. dest++;
  6. }
  7. while (*src) { // 复制 src 字符串到 dest 的末尾
  8. *dest++ = *src++;
  9. }
  10. *dest = '\0'; // 添加字符串结束符
  11. }
  12. int main() {
  13. char str1[50] = "Hello, ";
  14. char str2[] = "World!";
  15. concat(str1, str2);
  16. printf("%s\n", str1); // 输出: Hello, World!
  17. return 0;
  18. }
复制代码

4. 链表操作

链表是一种常见的数据结构,它的节点通常通过指针链接在一起。

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. typedef struct Node {
  4. int data;
  5. struct Node *next;
  6. } Node;
  7. void insert(Node **head, int data) {
  8. Node *newNode = (Node *)malloc(sizeof(Node));
  9. newNode->data = data;
  10. newNode->next = *head;
  11. *head = newNode;
  12. }
  13. void printList(Node *head) {
  14. Node *current = head;
  15. while (current != NULL) {
  16. printf("%d ", current->data);
  17. current = current->next;
  18. }
  19. printf("\n");
  20. }
  21. int main() {
  22. Node *head = NULL;
  23. insert(&head, 1);
  24. insert(&head, 2);
  25. insert(&head, 3);
  26. printList(head); // 输出: 3 2 1
  27. return 0;
  28. }
复制代码

5. 动态内存分配

使用 malloc、calloc 和 realloc 等函数在运行时动态地分配和重新分配内存。

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main() {
  4. int *arr = (int *)malloc(5 * sizeof(int));
  5. if (arr == NULL) {
  6. printf("Memory allocation failed\n");
  7. return 1;
  8. }
  9. for (int i = 0; i < 5; i++) {
  10. arr[i] = i + 1;
  11. }
  12. for (int i = 0; i < 5; i++) {
  13. printf("%d ", arr[i]);
  14. }
  15. printf("\n");
  16. free(arr); // 释放内存
  17. return 0;
  18. }
复制代码

四、相关链接

  1. Visual Studio Code下载地址
  2. Sublime Text下载地址
  3. 「C系列」C 简介
  4. 「C系列」C 基本语法
  5. 「C系列」C 数据类型
  6. 「C系列」C 变量及常见问题梳理
  7. 「C系列」C 常量
  8. 「C系列」C 存储类
  9. 「C系列」C 运算符
  10. 「C系列」C 判断/循环
  11. 「C系列」C 函数
  12. 「C系列」C 作用域规则
  13. 「C系列」C 数组
  14. 「C系列」C enum(枚举)

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

中国红客联盟公众号

联系站长QQ:5520533

admin@chnhonker.com
Copyright © 2001-2025 Discuz Team. Powered by Discuz! X3.5 ( 粤ICP备13060014号 )|天天打卡 本站已运行