一、指针部分知识
1.首先要准确地弄清楚指针的含义。指针就是地址,凡是出现“指针”的地方,都可以用“地址”代替,例如,变量的指针就是变量的地址,指针变量就是地址变量
2.区别指针和指针变量
- 指针就是地址本身
- 指针变量是用来存放地址的变量。
3.指针变量的类型决定了它所能指向的变量的类型
4.指针变量并不固定指向一个变量,可指向同类型的不同变量
5.如果两个指针变量都指向同一个数组中的元素,则两个指针变量值之差是两个指针之间的元素个数 ,如果p1和p2不指向同一数组则比较无意义
二、动态分配内存
- 非静态的局部变量是分配在内存中的动态存储区的,这个存储区是一个称为栈的区域
- C语言还允许建立内存动态分配区域,以存放一些临时用的数据,这些数据需要时随时开辟,不需要时随时释放。这些数据是临时存放在一个特别的自由存储区,称为堆区
- 对内存的动态分配是通过系统提供的库函数来实现的,主要有malloc,calloc,free,realloc这4个函数。
- 以上4个函数的声明在stdlib.h头文件中,在用到这些函数时应当用“#include <stdlib.h>”指令把stdlib.h头文件包含到程序文件中。
(1)malloc函数
- 其函数原型为
void *malloc(unsigned int size); - 其作用是在内存的动态存储区中分配一个长度为size的连续空间
- 函数的值是所分配区域的第一个字节的地址,或者说,此函数是一个指针型函数,返回的指针指向该分配域的开头位置
malloc(100);
开辟100字节的临时分配域,函数值为其第1个字节的地址 - 注意指针的基类型为void,即不指向任何类型的数据,只提供一个地址
- 如果此函数未能成功地执行(例如内存空间不足),则返回空指针(NULL)
(2)calloc函数
- 其函数原型为
void *calloc(unsigned n,unsigned size); - 其作用是在内存的动态存储区中分配n个长度为size的连续空间,这个空间一般比较大,足以保存一个数组。
- 用calloc函数可以为一维数组开辟动态存储空间,n为数组元素个数,每个元素长度为size。这就是动态数组。函数返回指向所分配域的起始位置的指针;如果分配不成功,返回NULL。如:
p=calloc(50,4);
开辟50×4个字节的临时分配域,把起始地址赋给指针变量p
(3)free函数
- 其函数原型为
void free(void *p); - 其作用是释放指针变量p所指向的动态空间,使这部分空间能重新被其他变量使用。p应是最近一次调用calloc或malloc函数时得到的函数返回值。
free(p);
释放指针变量p所指向的已分配的动态空间 - free函数无返回值
(4)realloc函数
- 其函数原型为
void *realloc(void *p,unsigned int size); - 如果已经通过malloc函数或calloc函数获得了动态空间,想改变其大小,可以用recalloc函数重新分配。
- 用realloc函数将p所指向的动态空间的大小改变为size。p的值不变。如果重分配不成功,返回NULL。如
realloc(p,50);
将p所指向的已分配的动态空间改为50字节
例:建立动态数组,输入5个学生的成绩,另外用一个函数检查其中有无低于60分的,输出不合格的成绩。
#include <stdio.h>
#include <stdlib.h>
int main()
{ void check(int *);
int *p1,i;
p1=(int *)malloc(5*sizeof(int));
for(i=0;i<5;i++)
scanf("%d",p1+i);
check(p1);
return 0;
}
void check(int *p)
{ int i;
printf("They are fail:");
for(i=0;i<5;i++)
if (p[i]<60)
printf("%d ",p[i]);
printf("\n");
}
三、链表
(1)静态链表
例:例 建立一个如图所示的简单链表,它由3个学生数据的结点组成,要求输出各结点中的数据。
#include <stdio.h>
struct Student
{ int num;
float score;
struct Student *next;
};
int main()
{ struct Student a,b,c,*head,*p;
a. num=10101; a.score=89.5;
b. num=10103; b.score=90;
c. num=10107; c.score=85;
head=&a; a.next=&b;
b.next=&c; c.next=NULL;
p=head;
do
{printf(“%ld%5.1f\n”,p->num,p->score);
p=p->next;
}while(p!=NULL);
return 0;
}
(2)动态链表
所谓建立动态链表是指在程序执行过程中从无到有地建立起一个链表,即一个一个地开辟结点和输入各结点数据,并建立起前后相链的关系。
例 写一函数建立一个有3名学生数据的单向动态链表。
#include <stdio.h>
#include <stdlib.h>
#define LEN sizeof(struct Student)
struct Student
{ long num;
float score;
struct Student *next;
};
int n;
struct Student *creat(void)
{
struct Student *head,*p1,*p2;
n=0;
p1=p2=( struct Student*) malloc(LEN);
scanf(“%ld,%f”,&p1->num,&p1->score);
head=NULL;
while(p1->num!=0)
{
n=n+1;
if(n==1)
head=p1;
else
p2->next=p1;
p2=p1;
p1=(struct Student*)malloc(LEN);
scanf(“%ld,%f”,&p1->num,&p1->score);
}
p2->next=NULL;
return(head);
}
int main()
{
struct Student *pt;
pt=creat();
printf(“\nnum:%ld\nscore:%5.1f\n”,pt->num,pt->score);
return 0;
}
例 编写一个输出链表的函数print
void print(struct Student *p)
{
printf("\nThese %d records are:\n",n);
if(p!=NULL)
do
{
printf("%ld %5.1f\n",p->num,p->score);
p=p->next;
}while(p!=NULL);
}