C语言教程-C语言中的空指针
到目前为止,我们学习了指针应该指向与指针声明中指定的类型相同的地址。例如,如果我们声明了一个int指针,那么这个int指针不能指向float变量或其他类型的变量,即它只能指向int类型的变量。为了解决这个问题,我们可以使用空指针(void指针)。空指针表示一个通用指针,可以指向任何数据类型。我们可以将任何数据类型的地址赋值给空指针,并且可以将空指针赋值给任何类型的指针,无需进行任何显式的类型转换。
空指针的语法
void *指针名;
以下是空指针的声明示例:
void *ptr;
在上述声明中,void是指针的类型,'ptr'是指针的名称。
让我们看一些示例:
int i = 9; // 整数变量初始化
int *p; // 整数指针声明
float *fp; // 浮点数指针声明
void *ptr; // 空指针声明
p = fp; // 错误的赋值
fp = &i; // 错误的赋值
ptr = p; // 正确的赋值
ptr = fp; // 正确的赋值
ptr = &i; // 正确的赋值
C中空指针的大小
在C中,空指针的大小与字符类型的指针的大小相同。根据C的观点,空指针的表示与字符类型的指针相同。指针的大小将根据您使用的平台而异。
让我们看下面的示例:
#include <stdio.h>
int main() {
void *ptr = NULL; // 空指针
int *p = NULL; // 整数指针
char *cp = NULL; // 字符指针
float *fp = NULL; // 浮点数指针
// 空指针的大小
printf("空指针的大小 = %d\n\n", sizeof(ptr));
// 整数指针的大小
printf("整数指针的大小 = %d\n\n", sizeof(p));
// 字符指针的大小
printf("字符指针的大小 = %d\n\n", sizeof(cp));
// 浮点数指针的大小
printf("浮点数指针的大小 = %d\n\n", sizeof(fp));
return 0;
}
输出
空指针的优势
以下是使用空指针的优势:
- malloc()和calloc()函数返回空指针,因此这些函数可以用于分配任何数据类型的内存。
#include <stdio.h>
#include <malloc.h>
int main() {
int a = 90;
int *x = (int*)malloc(sizeof(int));
x = &a;
printf("x指针所指的值:%d", *x);
return 0;
}
输出
- C中的空指针还可以用于实现通用函数。
与空指针相关的一些重要点:
- 在C中解引用空指针
不能直接解引用空指针。看下面的示例:
#include <stdio.h>
int main() {
int a = 90;
void *ptr;
ptr = &a;
printf("指针ptr所指的值:%d", *ptr);
return 0;
}
上面的代码中,*ptr是一个空指针,它指向整数变量'a'。由于我们已经知道空指针不能被解引用,所以上述代码会在编译时报错,因为我们直接打印了指针'ptr'所指的变量的值。
输出
现在,我们重写上面的代码以消除错误。
#include <stdio.h>
int main() {
int a = 90;
void *ptr;
ptr = &a;
printf("指针ptr所指的值:%d", *((int*)ptr));
return 0;
}
在上述代码中,我们通过使用以下语句将空指针强制转换为整数指针:
(int*)ptr;
然后,我们通过使用以下语句打印空指针'ptr'所指的变量的值:
*((int*)ptr);
输出
- 在空指针上进行算术运算
在C中,不能直接对空指针应用算术运算。我们需要进行适当的类型转换,以便可以对空指针进行算术运算。
看下面的示例:
#include<stdio.h>
int main() {
float a[4] = {6.1, 2.3, 7.8, 9.0};
void *ptr;
ptr = a;
for (int i = 0; i < 4; i++) {
printf("%f,", *ptr);
ptr = ptr + 1; // 错误的操作
}
}
上面的代码显示编译时错误"无效使用空表达式",因为我们不能直接对空指针应用算术运算,即ptr = ptr + 1
是不正确的。
让我们重写上面的代码以消除错误。
#include<stdio.h>
int main() {
float a[4] = {6.1, 2.3, 7.8, 9.0};
void *ptr;
ptr = a;
for (int i = 0; i < 4; i++) {
printf("%f,", *((float*)ptr + i));
}
}
上述代码成功运行,因为我们对空指针应用了适当的强制类型转换,即(float*)ptr
,然后我们对空指针应用算术运算,即*((float*)ptr + i)
。
输出
为什么使用空指针?
我们使用空指针是因为它具有可重用性。空指针可以存储任何类型的对象,并且我们可以通过使用间接操作符和适当的类型转换来检索任何类型的对象。
通过以下示例来理解:
#include<stdio.h>
int main() {
int a = 56; // 初始化整数变量'a'
float b = 4.5; // 初始化浮点数变量'b'
char c = 'k'; // 初始化字符变量'c'
void *ptr; // 声明空指针
// 分配变量'a'的地址
ptr = &a;
printf("变量'a'的值:%d\n", *((int*)ptr));
// 分配变量'b'的地址
ptr = &b;
printf("变量'b'的值:%f\n", *((float*)ptr));
// 分配变量'c'的地址
ptr = &c;
printf("变量'c'的值:%c\n", *((char*)ptr));
return 0;
}
输出