|||
新学到的有用的知识,怕忘了,按我的理解做个笔记。可为他人参考。
一、动态数组
C语言中不能直接定义动态数组,用普通的方式定义的数组其大小不能改变。如。通过int a[N];定义大小为N的整型数组,其后N的改变不会再改变原来数组大小。但我们可以间接地得到一个动态数组,即需要时通过malloc()或calloc()等动态存储分配函数分配一块空间,将其返回的所分配单元的起始地址赋给指针,我们就可以利用得到的指针进行和数组一样的操作。因为我们知道普通的数组名其实就是数组的起始地址,相当于一个指针常量。
例1,如我们想定义一个大小为n(例如10)的动态整型数组:
=====================
int *a;
int n;
n = 10; //此处设为10
a =(int *)malloc(sizeof(int)*n); /*动态分配存放10个整型的内存,将所分配空间起始地址转换为
整型地址赋给指针a*/
a[5] = 100; /*引用同一般数组,但不应超出所分配内存的大小
a[5]相当于*(a+5), 即从首地址向后跳过5个(整型)内存*/
free(a); //释放a所指的内存区
=====================
在知道地址和变量类型的情况下,a[i]等同于*(a+i),即从首地址开始跳过i个已知类型的数据元素。这两个内存函数原型为void *malloc(usigned size);和void *calloc(unsigned n, unsign size);它们包含在<stdlib.h>中。两者区别有二:一是前者分配size个字节大小的连续空间,后者分配n个size字节的连续空间。二是后者分配的内存初始化为0;而前者没有;如果想改变一个已分配地址的内存区的大小可以用函数void *realloc(void *p, unsign size)。这几个函数返回void 指针类型,赋值给其他类型指针时,需经过类型转换,系统一般在编译时也进行隐式转换。
二、多维动态数组
C语言中普通多维数组其实是一维数组,只不过各元素也是数组类型。想得到多维的的动态数组,可以嵌套使用前面的方法,如将得到的动态数组的元素a[i]再定义为动态数组。即定义指向指针的指针,再由外向内逐级分配空间。
例2:定义三维动态数组a[n1][n2][n3],其中n1,n2,n3为正整数:
==========================
int ***a; //定义指针的指针的指针
int n1, n2, n3;
int i, j, k;
scanf("%d%d%d",&n1,&n2,&n3);
a=(int ***)malloc(n1*sizeof(int **)); /*a有n1个元素,每个元素仍为数组(其实是指针的指针)
a为数组首地址,a[1],a[2],...,a[n1]为其子数组元素首地址,以此类推直至得到元素*/
for(i=0; i<n1; i++)
{
a[i]=(int **)malloc(n2*sizeof(int *)); //a[i]有n2个元素,每个元素为一维数组的首地址(其实是指针)
for(j=0; j<n2; j++)
{
a[i][j]=(int *)malloc(n3*sizeof(int)); //a[i][j]为一维数组,大小为n3
for(k=0; k<n3; k++)
{
a[i][j][k] = i*n2*n3+j*n3+k; //元素a[i][j][k]的引用同一般数组
}
}
}
.......;
//使用后要释放存储空间,注意由内向外逐级释放
for(i=0; i<n1; i++)
{
for(j=0; j<n2; j++) free(a[i][j]);
free(a[i]);
}
free(a);
=====================
多维数组分配存储空间从外往内,释放空间时要由从内往外。函数分配的内存空间,即使没有指针指向,它仍然存在,不自动回收,所以不能通过这定指针为空来释放空间。
以上通过指针和指向指针的指针在逻辑上模拟出一个动态数组。但其和普通的数组在内存分配上是不同的。真正的数组内存顺序分配,数组名并不单独开辟变量存储,其数组地址为一常数分配后不可改变,数组各维大小相等。动态模拟的数组不同维的元素并不连续,各维数组大小可以不同。
三、全局动态数组。
C语言的函数间参数传递为值传递,这与Fortran的地址传递不同。如果想通过调用函数来对原函数的变量进行操作可以将变量的指针(变量地址)传递给被调函数。另一种的方法是将变量设置为全局变量,这样其后的函数都可以对此变量进行操作了。如何定义一个全局动态数组呢,只要在函数体前声明一个全局指针,需要时在函数体内对此指针用malloc()或calloc()赋给地址即可。全局指针和其后分配的空间相当于一个全局数组。
例3,如我们想得到一个全局动态结构体数组
========================
struct mystruct
{ int b;
.......;};
struct mystruct *a; //在函数体外定义mystruct类型的全局结构体指针a
void main()
{ ......;
int n =10;
a=(struct mystruct *)malloc(sizeof(struct mystruct)*n); //在函数内分配存储空间,把首地址赋给全局指针
a[2].b = 100; //使用同普通结构体数组, 此数组为全局变量
.......;
free(a);
}
========================
引出:如何从文件中读取二进制数据到所分配的内存空间(或数组)呢?或者如何写到文件呢,很简但,用fread和fwrite就行。这两各函数用于在文件中读写数据块。
fread(buffer, size, count, fp);
fwrite(buffer, size, count, fp);
buffer是一个指针,指向读写数据快首地址。size要读写数据的字节数,count读写多少各size。fp文件型指针。
接上例如我们想从fp所指的文件读取一个大小为10的结构体数组
for(i=0; i<=9; i++)
fread(&a[i], sizeof(struct mystruct), 1, fp);
或者直接读取数组全部
fread(a, sizeof(struct mystrnct), 10, fp);
或
fread(a, sizeof(struct mystruct)*10, 1, fp);
2013年8月23日
Archiver|手机版|科学网 ( 京ICP备07017567号-12 )
GMT+8, 2024-10-19 22:42
Powered by ScienceNet.cn
Copyright © 2007- 中国科学报社