第一节 变量的地址
-
计算机中的内存:
内存每一个字节都有一个对应的地址编号,方便计算机快速找到对应内存空间,也可以将地址形象的称为
指针
。
int a = 6;
假如:系统分配10002~10005地址空间给a,存储int类型的数值6,并且生成变量a和地址10002的对照表。在执行代码时,通过变量名找到对应的地址,然后通过数 据类 型int获取4个字节空间内的信息,读取对应的数值。
scanf("%d", &a);
&
获取对应a变量的地址
,将键盘输入的值存入到对应地址内存中。
-
代码示例
#include <stdio.h> int main() { int a = 6; printf("%d\n", &a); //随机分配a的内存地址 return 0; }
#include <stdio.h> int main() { int a = 10, b = 12, c = 22; float d = 1.434f; printf("%d\t%d\t%d\t%d\n", &a, &b, &c, &d); //随机分配abcd的内存地址 printf("%d\n", sizeof(a)); //变量占据的空间大小 return 0; }
第二节 指针变量
-
存放地址的变量是指针变量,它用来指向另一个对象(如变量、数组、函数等)。
-
如果将一个变量b用来存储另一个变量a的地址(指针),称变量b为
指针变量
。int a = 10; int * b;
变量a的地址为10001,地址10001的内容为int类型数据10;
变量b的地址为10007,地址10007的内容为指针类型数据10001。
-
定义指针变量的一般形式为:
类型名 * 指针变量名;
代码示例:通过指针变量访问整型变量。
#include <stdio.h> int main() { int a = 100, b = 10; int* pointer_1, * pointer_2; pointer_1 = &a; pointer_2 = &b; printf("a = %d, b = %d\n", a, b); printf("* pointer_1 = %d, * pointer_2 = %d\n", * pointer_1, * pointer_2); return 0; }
-
定义指针变量时要注意:
-
指针变量前面的
*
表示该变量为指针型变量; -
在定义指针变量时必须
指定基类型(不同类型的数据在内存中所占的字节数和存放方式是不同德)
;指针或地址是包含有类型信息的,应使赋值号两侧的类型一致,以避免出现意外结果。如果指针是指向一个整型变量的,那么“使指针移动1个位置”意味着移动4个字节,“使指针增加1”意味着使地址值增加4个字节,必须指定指针变量所指向的变量的类型,即基类型
。一个指针变量只能指向同一个类型的变量。一个变量的指针的含义包含两个方面,一是以存储单元编号表示的纯地址(如编号为2000的字节),一是它指向的存储单元的数据类型(如int、char、float等)。 -
指向整型数据的指针类型表示为
int *
,读作“指向int的指针”或简称“int指针”。 -
指针变量中只能存放地址(指针),不要将一个整数赋给一个指针变量,如:
int * pointer_1 = 100; //pointer_1是指针变量,100是整数,不合法
可以在定义指针变量时,同时对它初始化,如:
int * pointer_1 = &a, * pointer_2 = &b; //定义指针变量pointer_1和pointer_2,并分别指向a,b
-
-
引用指针变量:
- 给指针变量赋值,如
p = &a;
,指针变量p的值是变量a的地址,p指向a。
- 给指针变量赋值,如
- 引用指针变量指向的变量。如果已执行
p = &a;
,即指针变量p指向了整型变量a,则printf("%d", *p);
的作用是以整数形式输出指针变量p所指向的变量的值,即变量a的值。如果有* p = 1;
,表示将整数1赋给p当前所指向的变量,如果p指向变量a,则相当于把1赋给a,即a = 1
。 - 引用指针变量的值,如
printf("%o", p);
作用是以八进制数形式输出指针变量p的值,如果p指向了a,就是输出了a的地址,即&a。
注意:
&
:取地址运算符,&a是变量a的地址。*
:指针运算符(或称“直接访问”运算符),*p代表指针变量p指向的对象。代码示例:
#include <stdio.h> int main() { int a = 3, b; int* p; p = &a; printf("%d\n", p); printf("%d\n", *p); b = *p; printf("%d\n", b); *p = 1; printf("%d\t%d\t%d\n", a, *p, b); return 0; }
-
指针变量作为函数参数:函数的参数不仅可以是整型、浮点型、字符型等数据,还可以是指针类型,它的作用是将一个变量的地址传送到另一个函数中。
代码示例:利用函数实现对输入的两个整数按大小输出
#include <stdio.h> int main() { void swap(int* pointer_1, int* pointer_2); int a, b; int* pointer_1, * pointer_2; printf("请输入两个数字:\n"); scanf("%d%d", &a, &b); pointer_1 = &a; pointer_2 = &b; if (a < b) swap(pointer_1, pointer_2); printf("max = %d\nmin = %d\n", a, b); return 0; } void swap(int* pointer_1, int* pointer_2) { int temp; temp = *pointer_1; *pointer_1 = *pointer_2; *pointer_2 = temp; }
-
第三节 通过指针引用数组元素
-
数组元素的指针
- 变量有地址,同样的数组元素也有地址,也可以通过指针指向数组元素。
- 数组名代表数组中第一个元素的地址。并不是代表整个数组。
代码示例:
#include <stdio.h> int main() { int a[5] = {9,3,2,4,3}; int * p; p = &a[0]; printf("%d\n", p); //打印出a[0]的地址 printf("%d\n", a); //与上述结果相同 return 0; }
-
数组元素的指针运算
-
当
指针
指向数组元素
时,可以对指针进行加减运算:p+1: 指向同一个数组中的下一个元素地址,不是地址数值+1,根据定义的类型大小增加。(++)
p -1: 指向同一个数组中的上一个元素地址,不是地址数值 -1 ,根据定义的类型大小减小。(–)
#include <stdio.h> int main() { int a[] = {9,3,2,4,3}; int * p = a; printf("%d\t%d\n", p+1, *(p+1)); ++p; ++p; printf("%d\t%d\n", p, *p); return 0; }
如果p = &a[0], p+3 是a[3]的地址,也等效于a+3;
#include <stdio.h> int main() { int a[] = {9,3,2,4,3}; int *p; p = &a[0]; printf("%d\t%d\t%d\t%d\n", p+3, a+3, *(p+3), a[3]); return 0; }
(p+3)获取p+3地址的数组元素。[ ]实际是变址运算符,a[i]等效为(a+i);
如果p1和p2指向
同一个
数组中的元素,则p2-p1的结果为二者之间的元素个数。#include <stdio.h> int main() { int a[] = {9,3,2,4,3}; int *p1, *p2; p1 = &a[1]; p2 = &a[4]; printf("p2-p1的结果为:%d\n", p2-p1);//(p1-p2)/4 = 3,p1和p2之间相差3个元素 return 0; }
-
-
指针引用数组元素
-
通过指针的方法引用数组元素的方法:
(1)下标法 例如:a[i]
#include <stdio.h> int main() { int a[10], i; for (i = 0; i < 10; i++) scanf("%d", &a[i]); for (i = 0; i < 10; i++) printf("%d\t", a[i]); //a[i] <==>*(a+i) return 0; }
(2)指针法 例如:(a+i)或(p+i),其中a是数组名,p是指向数组元素的指针变量。
#include <stdio.h> int main() { int a[10], i, *p = a; for (i = 0; i < 10; i++) scanf("%d", p + i);//p + i <==> a + i /* for (i = 0; i < 10; p++,i++) printf("%d\t", *p); */ for (i = 0; i < 10; i++) printf("%d\t", *p++);//*p++同优先级,综合方向从右往左,*++p地址多加一个,从第下标为1的数值开始打印 return 0; }
如果p = &a[i];则:
*(p++)表示先对p取地址内容,然后下一次p的地址减1
*(++p)表示先对p自加,然后取地址内容
#include <stdio.h> int main() { int a[5] = {9,3,2,4,3}; int *p = &a[1]; printf("%d\n", p); printf("%d\n", *(p--));//3 printf("%d\n", p); printf("%d\n", *p);//9 return 0; }
-
注意:
(1)a是数组首元素的地址,是一个常量,不能通过a++等方式改变a的值。
(2)当指针p指向数组元素时,指针p可以使用p[i]带下标的方式。当p = a时,p[i] = a[i].当p = &a[2],p[i] = a[i+2]。
#include <stdio.h> int main() { int a[5] = {9,3,2,4,3}; int *p = &a[1]; printf("%d\n", p[2]);//4 printf("%d\n", *(p));//3 return 0; }
-
-
用数组名作函数参数
-
函数如果传递数组名时,传递的是数组首地址,且如果形参数组中各元素的值发生变化,则实参数组元素的值也跟着改变。
-
传递参数是变量时,主函数中的变量不会被改变。
#include <stdio.h> int main() { int ff(int a); int a = 10; ff(a); printf("主函数中a的值:%d\n", a); return 0; } int ff(int a) { a = 3; printf("ff函数中a的值:%d\n", a); }
-
函数传递数组名时,形参数组中元素的值如果发生变化,实参数组元素的值也跟着改变。
#include <stdio.h> int main() { int ff(char a[]); char a[] = "peogeam"; ff(a); //传递的是数组首地址 printf("%s\n", a); //printf("%d\n", a); return 0; } int ff(char a[]) { //创建数组,但经过编译后,自动创建为一个指针变量a a[1] = 'r'; //[]变址运算符,a[1] = *(a+1) a[4] = 'r'; //printf("%d\n", a); }
形参经过编译后,自动编译为一个指针变量a,因此形参的定义[ ]中括号中可以是任意数值;
-
实参数组名,形参指针名
#include <stdio.h> int main() { int ff(char *a); char a[] = "peogeam"; ff(a); printf("%s\n", a); return 0; } int ff(char *a) { a[1] = 'r'; //*(a+1) = 'r' a[4] = 'r'; //*(a+4) = 'r' //printf("%d\n", a); }
-
实参指针名,形参数组名
#include <stdio.h> int main() { int ff(char *a); char a[] = "peogeam"; char *p = a; ff(a); //ff(p); printf("%s\n", a); return 0; } int ff(char a[]) { a[1] = 'r'; //*(a+1) = 'r' a[4] = 'r'; //*(a+4) = 'r' }
-
形参和实参都用指针名
#include <stdio.h> int main() { int ff(char *a); char a[] = "peogeam"; char *p = a; ff(p); printf("%s\n", a); return 0; } int ff(char *a) { *(a+1) = 'r' *(a+4) = 'r' }
-
练习:将数组中n个元素按相反顺序存放。
#include <stdio.h> int main() { int over(char *p); int ff(char *a); char a[] = "program"; char *p; p = a; over(p); printf("颠倒后的内容是:%s\n", a); return 0; } int over(char *p) { char t; int i; for (i = 0; i < 3; i++){ t = *(p+i); *(p+i) = *(p+6-i); *(p+6-i) = t; } }
-
-
通过指针引用多维数组
- 现有一个二维数组:
int a[3][4] = {{3,8,6,2},{5,6,3,9},{2,5,3,0}};
a包含3行,分别用a[0], a[1], a[2]表示。
二维数组地址说明:
(1)a代表二位数组首行的起始地址1244952
(2)a+1代表序号为1的行的地址1244968
计算方法:1244952+4*4 = 1244968
(3)
a[0],a[1],a[2]
是一维数组名,也是各行的首地址。
a[0] = &a[0][0] = *(a+0)
a[1] = &a[1][0] = *(a+1)
a[2] = &a[2][0] = *(a+2)
(4)
a[0]
是一维数组名,则a[0]+1
表示a[0][1]
的地址
a[1] + 2
表示a[1][2]
的地址,即&a[1][2]
a[1]+2 = *(a+1) +2 = &a[1][2]
(5)
a[0][2] = *(a[0]+2) = *(*(a+0) +2)
a[1][2] = *(a[1]+2) = *(*(a+1) +2)
注意:
a+1 和a[1]的结果一样,但是性质不同。a+1指向第2行(属性为行),a[1]指向第2行首元素地址(属性为元素),因为C语言的地址信息中即包含了位置信息,也包含了数据的类型信息。
例如 a+1再加1,是下一行,而a[1]+1是下一个元素。
-
多维数组
#include <stdio.h> int main() { int a[3][4]={{3,8,6,2},{5,6,3,9},{2,5,3,0}}; printf("a=%d\t a+1=%d\n",a,a+1); printf("a[0]=%d\t a[2]=%d\n",a[0],a[2]);//a[0],a[1],a[2]是一维数组名,也是各行的首地址 printf("&a[0][0]=%d\t *(a+0)=%d\n",&a[0][0],*(a+0)); printf("&a[1][0]=%d\t *(a+1)=%d\n",&a[1][0],*(a+1)); printf("a[1]+2=%d\t *(a+1)+2=%d\n",a[1]+2,*(a+1)+2); printf("a[1][2]=%d\t *(a[1]+2)=%d\t *(*(a+1)+2)=%d\n",a[1][2],*(a[1]+2),*(*(a+1) +2)); }
-
输出多维数组
#include <stdio.h> int main() { int a[3][4]={{3,8,6,2},{5,6,3,9},{2,5,3,0}}; int *p; //(*p)[4] for (p = a[0]; p < a[0] + 12; p++) printf("%d\t", *p); return 0; }
- 现有一个二维数组:
第四节 通过指针引用字符串
- 字符串的引用方式:
- 用字符数组存放一个字符串,可以通过数组名和下标引用字符串中一个字符,也可以通过数组名和格式声明“%s”输出该字符串。
- 用字符指针变量指向一个字符串常量,通过字符指针变量引用字符串常量。
代码示例:字符数组存储字符串
#include <stdio.h>
int main()
{
char gq[] ="Happy birthday motherlan";
printf("%s\n",gq);
}
代码示例:字符指针指向字符串常量
#include <stdio.h>
int main()
{
char *gq = "Happy birthday to our motherlan"; //定义了一个字符指针变量,指向字符串常量第1个元素的地址
printf("%s\n",gq); //%s通过gq找到字符串首地址,不断使gq加1,使之指向下一个字符,再输出字符,直到\0
printf("%d\n",gq); //打印指针变量的地址
gq = "Happy birthday"; //在内存中重新开辟内存空间存储字符串常量
printf("%s\n",gq);
printf("%d\n",gq);
注意:
-
%s是通过字符指针找到字符串常量的首地址,使地址不断加1,直到遇到
\0
为止,输出地址对应内容。 -
对数值型数组是不能通过%s一次性输出全部元素,只能元素逐个输出。
练习:将数组x中的字符逐个复制到数组y中
#include <stdio.h>
int main() {
char x[] = "C program";
char y[15];
int i;
for (i = 0; *(x + i) != '\0'; i++) //x[i] = *(x + i)
* (y + i) = * (x + i); //y[i] = x[i]
*(y + i) = '\0'; //y[i] = '\0';
printf("%s\n", y);
return 0;
}
-
字符指针作函数参数
把一个字符串从一个函数传递到另一个函数,可以用
地址传递
的方法,即用字符数组名作参数,也可以用字符指针变量作参数。-
代码示例:用函数调用实现字符串的复制。
#include <stdio.h> int main() { int cp(char* old_str, char* new_str); char str1[] = "I am a boy"; char str2[20]; cp(str1, str2); printf("赋值后的字符串为:%s\n", str2); return 0; } int cp(char * old_str, char * new_str) { int i; for (i = 0; old_str[i] != '\0'; i++) new_str[i] = old_str[i]; new_str[i] = '\0'; }
-
-
使用字符指针变量和字符数组的比较
用字符数组和字符指针变量都能实现字符串的存储和运算,但二者之间有区别:
-
字符数组包含多个元素,每个元素都有自己的地址,而字符指针变量中存放的是地址。
-
可以对字符指针变量赋一个地址,但不能对字符数组名赋值,它是一个常量。
-
字符数组除了在初始化时可以一次性对所有元素赋值,非初始化部分不能一次性赋值,但字符指针变量可以实现。
-
编译时为字符数组分配若干存储单元,以存放各元素的值,而对字符指针变量,只分配一个存储单元。可能指向内存中空白的(未用的)用户存储区中,也有可能指向已存放指令或数据的有用内存段,会破坏程序或有用数据,甚至破坏系统,造成严重后果。
-
字符数组的元素值可以被改变,但
字符指针指向的字符串常量中的元素不能被改变
。#include <stdio.h> int main() { // char a[] = "dioo"; // char *p = "dioo"; // a = "dada"; // p = "dada"; // char *p; // scanf("%s",p); char a[] = "dioo"; char *p = "dada"; //不可被修改 a[1] = 'Y'; p[1] = 'Z'; printf("%s\n%s\n",a,p); }
-
使用字符指针变量指向的字符串或字符数组都可以实现printf函数的可变格式输出。
#include <stdio.h> int main() { int a = 3, b = 100; char * p = "a=%d\t b = %d\n"; printf(p,a,b); return 0; }
-
第五节 指向函数的指针
-
什么是函数的指针?
-
程序代码中的函数在编译时,会分配一段存储空间存储函数可执行代码,函数名代表函数的起始地址。调用该函数时,会从函数名处找到函数的起始地址,并执行对应函数。
-
函数名
就是函数的指针,代表函数的起始地址。 -
定义一个指针变量用于指向函数,存放函数的起始地址,则此指针为
函数指针变量
。 -
代码示例:打印菱形
#include <stdio.h> int main() { void print_star(); void (*p)(); p = print_star; printf("打印菱形:\n"); (*p)(); printf("第二次打印菱形:\n"); (*p)(); printf("最后一次打印菱形:\n"); (*p)(); return 0; } void print_star() { char a[5][5] = { {' ', ' ', '*'}, {' ', '*', ' ', '*'}, {'*', ' ', ' ', ' ', '*'}, {' ', '*', ' ', '*'}, {' ', ' ', '*'} }; int i, j; for (i = 0; i < 5; i++) { for (j = 0; j < 5; j++) printf("%c", a[i][j]); printf("\n"); } }
-
-
定义函数指针变量
-
定义指向函数的指针变量的一般形式为:
类型名 (* 指针变量名)(函数参数表列);
-
注意:
- 定义函数指针变量之前需要确定好类型名,类型名代表可以指向的函数类型。例如:
int ( *p )(int ,int)
代表指针p只能指向int类型的函数,且对应的函数有两个整型形参。* * 指针变量名
需要用括号括起来。- 给函数指针变量赋值时,只需给出函数名, 不用写入参数。
(*指针名)是调用函数,使用(*指针名)替代函数名即可
。- 函数指针变量没有加减运算,是无意义的运算。
- 定义函数指针变量之前需要确定好类型名,类型名代表可以指向的函数类型。例如:
-
函数指针变量对比函数名的两者使用的优点:
函数名调用函数,只能调用指定的一个函数,而函数指针变量可以通过改变指针变量的地址灵活调用不同的函数。
-
代码示例:通过指针求二者中的较大者
#include <stdio.h> int main() { int max(int x, int y); int a, b; int (*p)(int, int); printf("请输入要比较的两个数字:\n"); scanf("%d%d", &a, &b); p = max; printf("max = %d\n", (*p)(a, b)); return 0; } int max(int x, int y) { return x > y ? x : y; }
-
-
用指向函数的指针作函数参数
指向函数的指针变量的一个重要用途是把函数的
入口地址
作为参数传递到其他函数。在实际使用中,常常将函数指针作为另一个函数的参数,传递到其他函数中。例如函数指针变量p指向函数a,函数b中的一个参数为变量p:
int b( int ( *p ));
-
代码示例:有两个整数a和b,由用户输入并选择执行操作。
#include <stdio.h> int main() { int max(int x, int y); int min(int x, int y); int add(int x, int y); int a, b, n; printf("请输入两个数字:\n"); scanf("%d%d", &a, &b); printf("请选择方案1,2,3:"); scanf("%d", &n); if (n == 1) fun(a, b, max); else if (n == 2) fun(a, b, min); else if (n == 3) fun(a, b, add); return 0; } int max(int x, int y) { return x > y ? x : y; } int min(int x, int y) { return x < y ? x : y; } int add(int x, int y) { int z; z = x + y; return z; } int fun(int x, int y, int (*p)(int, int)) { int result; result = (*p) (x, y); printf("%d\n", result); }
-
第六节 返回指针的函数
-
函数除了可以返回整型、字符、浮点数等以外,还可以返回指针。
-
定义返回指针值的函数的原型的一般类型为:
类型名 * 函数名(参数表列);
返回指针的方法:通过return函数返回指针变量名。
-
代码示例:
#include<stdio.h> char *max(char *a, char *b) { int i,flag; for(i = 0;i<4;i++) { if(a[i]<b[i]) { flag = 0; break; } else if(a[i]> b[i]) { flag = 1; break; } } if(flag == 0) return b; else return a; } void main() { char a[] = "bbyd"; char b[] = "zbda"; char *p; p = max(a,b); printf("%s\n",p); }
-
第七节 指针数组和多重指针
-
一个数组,若其元素均为指针类型数据,称为
指针数组
,也就是说,指针数组中的每一个元素都存放一个地址,相当于一个指针变量。-
定义一维指针数组的一般形式为:
类型名 * 数组名[数组长度];
-
使用场景:当有多个字符串时,可以使用指针数组处更加灵活。
-
代码示例:
#include<stdio.h> s[0]= "C program" s[1] = "control" s[2] = "logic" void main() { int i; char *s[]={"C program","control","logic"};//char s[][9] = {"C program","control","logic"}不灵活; for(i = 0;i<3;i++) printf("%s\n",s[i]); }
-
-
指向指针数据的指针变量(多重指针)
-
一个指针变量指向另一个指针称为
多重指针
。 -
定义多重指针的方法:
指针类型 **指针名;//char **p;
理论上可以出现3重地址,甚至更多重地址,但是通常间接访问变量一般不会超过二级地址。级数越多越难于理解和使用。
-
代码示例:
#include <stdio.h> int main() { int a = 3; int *p = &a; int **y = &p; printf("%d\n",a); //3 printf("%d\n",*p); //3 printf("%d\n",**y); //3 return 0; }
#include <stdio.h> int main() { char *s[]={"C program","control","logic"}; char **p; p = s+1; printf("%s\n",*p); printf("%d\n",*p); printf("%c\n",**p); return 0; }
-
-
指针数组作main函数的形参
-
指针数组的一个重要应用是作为main函数的形参,一般写成
int main()
或int main(void)
,括号中是空的或有“void”,表示main函数没有参数,调用main函数时不必给出实参,这是一般程序常采用的形式。实际上,在某些情况下,main函数可以有参数,如:int main(int argc, char *argv[]);
其中argc和argv就是main函数的形参。argc接收参数个数,argv是字符指针数组。
-
如果用带参数的main函数,其第一个形参必须是int型,用来接收形参个数,第二个形参必须是字符指针数组,用来接收从
操作系统
命令行传来的字符串中首字符的地址(由操作系统传递实参给main函数。实参是和执行文件的命令一起给出的)。 -
main函数是操作系统调用的,实参只能由操作系统给出。在操作命令状态下,实参是和整型文件的命令一起给出的,例如在DOS,UNIX或Linux等系统的操作命令状态下,在命令行中包括了命令名和需要传给main函数的参数,命令行的一般形式为:
命令名 参数1 参数2 ··· 参数n
。其中命令名为可执行文件名(包含main函数的.exe文件),各个参数之间用空格分隔。
-
第八节 动态内存分配与指向它的指针变量
-
全局变量是分配在内存中的静态存储区的,非静态的局部变量(包括形参)是分配在内存中的动态存储区的,这个存储区是一个称为
栈(stack)
的区域。除此以外,C语言还允许建立内存动态分配区域,以存放临时用的数据,这些数据不必在程序的声明部分定义,也不必等到函数结束时才释放,而是需要时随时开辟,不需要时随时释放。这些数据是临时存放在一个特别的自由存储区,称为堆(heap)
区。 -
对内存的动态分配是通过系统提供的库函数来实现的,主要有malloc,calloc,free,realloc这4个函数。
-
用malloc函数开辟动态存储区,其函数原型为
void * malloc(unsigned int size);
。其作用是在内存的动态存储区中分配一个长度为size的连续空间。malloc(100); //开辟100字节的临时分配域,函数值为其第1个字节的地址
注意指针的基类型为void,即不指向任何类型的数据,只提供一个纯地址。如果此函数未能成功执行(例如内存空间不足),则返回空指针(NULL)。
-
用calloc函数开辟动态存储区,其函数原型为
void * calloc(unsigned n, unsigned size);
。其作用是在内存的动态存储区中分配n个长度为size的连续空间,这个空间一般比较大,足以保存一个数组。用calloc函数可以为一维数组开辟动态存储空间,n为数组元素个数,每个元素长度为size。这就是动态数组。函数返回指向所分配域的第一个字节的指针;如果分配不成功,返回NULL,如:
p = calloc(50, 4); //开辟50×4个字节的临时分配域,把首地址赋给指针变量p
-
用realloc函数重新分配动态存储区,其函数原型为
void * realloc(void * p, unsigned int size);
。如果已经通过malloc或calloc函数获得了动态空间,想改变其大小,可以用realloc函数重新分配
。用realloc函数将p所指向的动态空间的大小改变为size。p的值不变。如果重分配不成功,返回NULL,如:
realloc(p, 50); //将p所指向的已分配的动态空间改为50字节
-
用free函数释放动态存储区,其函数原型为
void free(void *p);
。其作用是释放指针变量p所指向的动态空间,使这部分空间能重新被其他变量使用。p应是最近一次调用calloc或malloc函数时得到的函数返回值,如:free(p); //释放指针变量p所指向的已分配的动态空间
free函数无返回值。
-
-
void指针类型
- C99允许使用基类为void的指针类型。可以定义一个基类型为void的指针变量(即void * 型变量),它不指向任何类型的数据。请注意:不要把“指向void类型”理解为能指向“任何的类型”的数据,而应理解为“指向空类型”或“不指向确定的类型”的数据。在将它的值赋给另一指针变量时由系统对它进行类型转换,使之适合于被赋值的变量的类型。