C语言指针专题五 -- void和const指针
目录
一、void指针(通用指针)
1. 核心原理
2. 代码示例
二、const指针(常量指针)
1. 核心原理
2. 代码示例
三、void指针与const指针的结合使用
四、关键总结
一、void
指针(通用指针)
1. 核心原理
-
无类型指针:
void*
是一种通用指针类型,可以指向任意类型的数据,但 不能直接解引用(需强制类型转换)。 -
用途:
-
实现泛型编程(如
qsort
、memcpy
等标准库函数)。 -
动态内存分配时返回未指定类型的指针。
-
-
特点:
-
赋值给其他类型指针时需显式类型转换。
-
不接受指针算术运算(如
void* p++;
是非法的,因为步长未知)。
-
2. 代码示例
示例1:泛型交换函数
#include <stdio.h>
#include <string.h>
// 使用void*实现通用数据交换
void swap(void *a, void *b, size_t size) {
char temp[size]; // 使用字符数组暂存数据(按字节操作)
memcpy(temp, a, size);
memcpy(a, b, size);
memcpy(b, temp, size);
}
int main() {
int x = 10, y = 20;
printf("Before swap: x=%d, y=%d\n", x, y);
swap(&x, &y, sizeof(int));
printf("After swap: x=%d, y=%d\n", x, y); // 输出x=20, y=10
double a = 3.14, b = 6.28;
printf("Before swap: a=%.2f, b=%.2f\n", a, b);
swap(&a, &b, sizeof(double));
printf("After swap: a=%.2f, b=%.2f\n", a, b); // 输出a=6.28, b=3.14
return 0;
}
示例2:动态内存分配与类型转换
#include <stdio.h>
#include <stdlib.h>
int main() {
void *ptr = malloc(sizeof(int)); // 分配int类型内存
if (ptr == NULL) {
printf("内存分配失败!\n");
return 1;
}
// 转换为int*后赋值
int *int_ptr = (int*)ptr;
*int_ptr = 42;
printf("值: %d\n", *int_ptr); // 输出42
free(ptr); // 释放内存
return 0;
}
二、const
指针(常量指针)
1. 核心原理
-
保护数据不被修改:
const
关键字用于限制指针的访问权限,根据const
的位置不同,分为三种情况:-
指向常量的指针(
const int* p
):-
指针可以指向其他地址,但 不能通过指针修改数据。
-
-
指针本身为常量(
int* const p
):-
指针的指向不可变,但 可以修改指向的数据。
-
-
指向常量的常量指针(
const int* const p
):-
指针的指向和指向的数据均不可变。
-
-
2. 代码示例
示例1:指向常量的指针
#include <stdio.h>
int main() {
int a = 10;
const int *p = &a; // p指向的数据不可修改
printf("初始值: %d\n", *p); // 输出10
// *p = 20; // 错误!无法通过p修改a的值
int b = 30;
p = &b; // 合法:p可以指向其他地址
printf("新值: %d\n", *p); // 输出30
return 0;
}
示例2:常量指针
#include <stdio.h>
int main() {
int a = 10;
int *const p = &a; // p的指向不可变
*p = 20; // 合法:可以修改指向的数据
printf("a的值: %d\n", a); // 输出20
int b = 30;
// p = &b; // 错误!p的指向不可修改
return 0;
}
示例3:指向常量的常量指针
#include <stdio.h>
int main() {
int a = 10;
const int *const p = &a; // 指向和值均不可变
printf("值: %d\n", *p); // 输出10
// *p = 20; // 错误!不可修改数据
// p = NULL; // 错误!不可修改指向
return 0;
}
示例4:函数参数中的const
指针
#include <stdio.h>
// 使用const保护数据不被修改
void print_array(const int *arr, int size) {
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
// arr[i] = 0; // 错误!无法修改数据
}
printf("\n");
}
int main() {
int arr[] = {1, 2, 3, 4, 5};
print_array(arr, 5); // 输出1 2 3 4 5
return 0;
}
三、void
指针与const
指针的结合使用
#include <stdio.h>
// 泛型打印函数(数据只读)
void print_data(const void *data, char type) {
switch (type) {
case 'i':
printf("整数值: %d\n", *(const int*)data);
break;
case 'f':
printf("浮点值: %.2f\n", *(const float*)data);
break;
default:
printf("未知类型\n");
}
}
int main() {
int a = 42;
float b = 3.14;
print_data(&a, 'i'); // 输出整数值: 42
print_data(&b, 'f'); // 输出浮点值: 3.14
return 0;
}
四、关键总结
注意事项:
-
void*
转换安全:强制类型转换需确保目标类型正确,否则可能导致数据错误。 -
const
保护机制:编译器会检查const
约束,违反时会报错。