C语言学习笔记(二):void指针和malloc函数

在讲void指针之前,我们先回忆一下指针:

int *p;
char *q;

这里定义了两个指针变量p和q,其中,p指向返回值类型为int的变量,q指向返回值为char的变量。

而void是一种无类型指针,它表示不知道指向什么类型的指针,所以void指针可以指向任意类型的数据。做运算时,void相当于char(只针对部分编译器而言),但是和char*并不相通。*

如下,当普通指针进行强制类型转换时可能会出现错误:

#include 

int main() {
	char i1[4] = {'a', 'b', 'c', 'd'};
	char *p1 = &i1;
	for (int i = 0; i < 4; i++)
		printf("%c\n", i1[i]);

	//让指向char数组的char指针为0
	*p1 = 0;
	for (int i = 0; i < 4; i++)
		printf("%d\n", i1[i]);//ASCII值为0的时候对应的字符是NULL,控制台什么都不会显示(或者说显示的是空字符),所以这里我们换成十进制输出

	//让指向char数组的int指针为0
	int *p2 = (int *)p1;
	*p2 = 0;
	for (int i = 0; i < 4; i++)
		printf("%d\n", i1[i]);

	return 0;
}

C语言学习笔记(二):void指针和malloc函数_第1张图片
当我们把一个char指针强制转换成int指针后(不建议这样做,编译时会出现warning),它从指向一个字节变成了指向连续的四个字节,此时我们对这个int指针赋值,会导致连续的四个字节的变量都会被覆盖,从而导致值的丢失。

任何类型的指针都可以直接赋值给 void 指针,而它会无条件接受,且无需进行其他相关的强制类型转换,所以可以使用void指针作为函数参数,这样就不会造成精度丢失或者值意外被覆盖。不过要将 void 指针赋值给其他类型的指针,必须进行强制类型转换。

讲完了void*我们就可以更好地理解malloc函数。

如果我们需要一个变长的数组,可以定义一个int型的长度length,然后通过scanf确定Array[length]的长度。

但是,C99之前,数组的下标不能是变量,所以当我们提前不知道数组长度时,需要用malloc函数动态地分配内存,通过运行时输入的数值决定申请多少字节的内存。

使用malloc这个函数需要包含stdlib.h头文件,其函数原型为

void*malloc(size_t size);

其中size是申请的空间大小,单位为字节。
我们可以用malloc()向系统申请空间,申请到的空间是void无类型的,在计算机看来,内存就是连续的空间,它并不在意你申请的是什么类型,更在意的是你申请了多少字节。用malloc()申请空间之后我们可以自由决定它的类型。
比如像这样:

#include
#include
int main(){
	int length;
	int*arr;
	printf("输入长度:\n");
	scanf("%d",&length);
	arr=(int*)malloc(length*sizeof(int));
	printf("输入数组的值:\n");
	for(int i=0;i<length;i++){
		scanf("%d",&arr[i]);
    }
    free(arr);
    return 0;
}

运行结果如下:
C语言学习笔记(二):void指针和malloc函数_第2张图片

数组是const类型的特殊指针,所以我们可以对指针类似数组使用,用[ ]操作。
用malloc()申请空间后还要用free()释放,malloc()和free()成对出现。
free函数原型如下:

void*free(void *ptr);

注意这里free的指针变量必须是当初申请的首地址,如果我们对malloc()的指针变量p进行了运算,例如自增自减(p++、p–),仍然free的是p,这时候p已经不是当时申请的首地址了,计算机无法正确地回收内存空间。

你可能感兴趣的:(c语言)