文章目录
- 一、C 指针
- 1. 指针的定义
- 2. 指针的初始化
- 3. 指针的解引用
- 4. 指针的运算
- 5. 动态内存分配
- 6. 指针的NULL初始化
- 7. 指针作为函数参数和返回值
- 8. 指针数组和数组指针
- 9. 多级指针
- 二、C语言中有哪些内置的指针操作符
- 三、常见应用案例
- 1. 交换两个变量的值
- 2. 数组与指针
- 3. 字符串操作
- 4. 链表操作
- 5. 动态内存分配
- 四、相关链接
一、C 指针
在C语言中,指针是一个非常重要的概念,它允许程序直接访问内存地址,并操作该地址上存储的数据。指针本身是一个变量,但它存储的不是实际的数据值,而是存储数据值的内存地址。
以下是关于C语言中指针的一些基本概念和用法:
1. 指针的定义
指针变量通常通过以下方式定义:
int *ptr; // 定义一个指向int类型数据的指针变量ptr
这里的int *
是一个类型,表示这是一个指向int
类型数据的指针。
2. 指针的初始化
在定义指针变量后,通常需要将其初始化为一个有效的内存地址。这可以通过以下方式完成:
int x = 10;
int *ptr = &x; // 将ptr初始化为x的地址
在这里,&
是一个取地址运算符,它返回变量x
在内存中的地址。
3. 指针的解引用
解引用指针意味着访问指针所指向的内存地址上的数据。这可以通过在指针变量前加*
来实现:
int y = *ptr; // 将ptr所指向的int值(即x的值)赋值给y
4. 指针的运算
指针可以进行一些基本的算术运算,如加法、减法等。但这些运算不是基于指针的值(即内存地址),而是基于指针所指向的数据类型的大小。例如,如果ptr
是一个指向int
的指针,那么ptr + 1
将指向下一个int
类型的内存位置。
5. 动态内存分配
在C语言中,可以使用malloc
和calloc
等函数在运行时动态地分配内存,并将返回的内存地址存储在指针变量中。例如:
int *array = (int *)malloc(10 * sizeof(int)); // 分配一个包含10个int的数组的内存
注意:在使用完动态分配的内存后,应使用free
函数释放内存,以避免内存泄漏。
6. 指针的NULL初始化
为了避免野指针(指向无效内存地址的指针),通常会将指针初始化为NULL:
int *ptr = NULL;
7. 指针作为函数参数和返回值
指针经常作为函数的参数和返回值,以实现数据的间接访问和修改。例如,一个交换两个整数值的函数可以接收两个指向整数的指针作为参数:
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
8. 指针数组和数组指针
- 指针数组:一个数组,其元素是指针。
- 数组指针:一个指针,指向数组的首个元素。
这两者在语法和用途上有所不同,需要仔细区分。
9. 多级指针
在C语言中,还可以定义指向指针的指针,即多级指针。例如,int **ptr
是一个指向int
指针的指针。多级指针在某些复杂的数据结构和算法中非常有用。
二、C语言中有哪些内置的指针操作符
在C语言中,与指针相关的内置操作符主要有以下几个:
- 取地址操作符(&)
- 这个操作符用于获取变量的内存地址。
- 示例:
int x = 10; int *ptr = &x;
这里,&x
就是取变量x
的地址,并将这个地址赋值给指针ptr
。
- 解引用操作符(*)
- 这个操作符用于访问指针所指向的内存地址中的数据。
- 示例:
int y = *ptr;
这里,*ptr
就是访问ptr
所指向的内存地址上的数据,并将其赋值给变量y
。 - 当
*
出现在声明中时,它表示指针的类型;但在表达式中,它表示解引用操作。
- 指针算术操作符(+ 和 -)
- 这两个操作符用于指针的算术运算。
- 当用于指针时,它们基于指针所指向的数据类型的大小进行运算。例如,对于指向
int
的指针,ptr + 1
会将指针向前移动一个int
的大小。 - 示例:
ptr++
和ptr += 2
等都是有效的指针算术操作。
- 指针比较操作符(==、!=、<、<=、>、>=)
- 这些操作符用于比较两个指针是否指向相同的内存地址,或者它们在内存中的相对位置。
- 需要注意的是,只有当两个指针指向同一数组(或同一块内存区域)中的元素时,比较它们的大小才有意义。
- -> 操作符(结构体指针的成员访问)
- 这个操作符用于通过结构体指针访问结构体的成员。
- 示例:如果
struct_ptr
是一个指向结构体的指针,并且该结构体有一个名为member
的成员,则可以使用struct_ptr->member
来访问这个成员。
- . 操作符(结构体的成员访问)
- 虽然这不是一个专门的指针操作符,但在与结构体和指针一起使用时,
.
操作符用于通过结构体变量访问其成员。 - 示例:如果
struct_var
是一个结构体变量,并且该结构体有一个名为member
的成员,则可以使用struct_var.member
来访问这个成员。
需要注意的是,除了上述操作符之外,还有其他一些操作符(如赋值操作符 =
、自增/自减操作符 ++
和 --
等)也可以与指针一起使用,但它们并不是专门为指针设计的。
三、常见应用案例
C 语言中的指针具有广泛的应用,以下是一些常见的应用案例及其详细代码:
1. 交换两个变量的值
使用指针可以避免使用临时变量来交换两个变量的值。
#include <stdio.h>
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
int main() {
int x = 5, y = 10;
printf("Before swap: x = %d, y = %d\n", x, y);
swap(&x, &y);
printf("After swap: x = %d, y = %d\n", x, y);
return 0;
}
2. 数组与指针
在 C 语言中,数组名实际上是一个指向数组首元素的指针。
#include <stdio.h>
void printArray(int *arr, int size) {
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]); // 也可以使用 *(arr + i)
}
printf("\n");
}
int main() {
int arr[] = {1, 2, 3, 4, 5};
int size = sizeof(arr) / sizeof(arr[0]);
printArray(arr, size);
return 0;
}
3. 字符串操作
在 C 语言中,字符串是通过字符数组实现的,而字符串操作经常涉及到指针。
#include <stdio.h>
#include <string.h>
void concat(char *dest, const char *src) {
while (*dest) { // 找到 dest 字符串的末尾
dest++;
}
while (*src) { // 复制 src 字符串到 dest 的末尾
*dest++ = *src++;
}
*dest = '\0'; // 添加字符串结束符
}
int main() {
char str1[50] = "Hello, ";
char str2[] = "World!";
concat(str1, str2);
printf("%s\n", str1); // 输出: Hello, World!
return 0;
}
4. 链表操作
链表是一种常见的数据结构,它的节点通常通过指针链接在一起。
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node *next;
} Node;
void insert(Node **head, int data) {
Node *newNode = (Node *)malloc(sizeof(Node));
newNode->data = data;
newNode->next = *head;
*head = newNode;
}
void printList(Node *head) {
Node *current = head;
while (current != NULL) {
printf("%d ", current->data);
current = current->next;
}
printf("\n");
}
int main() {
Node *head = NULL;
insert(&head, 1);
insert(&head, 2);
insert(&head, 3);
printList(head); // 输出: 3 2 1
return 0;
}
5. 动态内存分配
使用 malloc
、calloc
和 realloc
等函数在运行时动态地分配和重新分配内存。
#include <stdio.h>
#include <stdlib.h>
int main() {
int *arr = (int *)malloc(5 * sizeof(int));
if (arr == NULL) {
printf("Memory allocation failed\n");
return 1;
}
for (int i = 0; i < 5; i++) {
arr[i] = i + 1;
}
for (int i = 0; i < 5; i++) {
printf("%d ", arr[i]);
}
printf("\n");
free(arr); // 释放内存
return 0;
}
四、相关链接
- Visual Studio Code下载地址
- Sublime Text下载地址
- 「C系列」C 简介
- 「C系列」C 基本语法
- 「C系列」C 数据类型
- 「C系列」C 变量及常见问题梳理
- 「C系列」C 常量
- 「C系列」C 存储类
- 「C系列」C 运算符
- 「C系列」C 判断/循环
- 「C系列」C 函数
- 「C系列」C 作用域规则
- 「C系列」C 数组
- 「C系列」C enum(枚举)