C语言重点笔记五(下)——指针与数组(一维数组,二维数组,动态存储分配)

文章详细介绍了如何通过数组名和指针变量访问数组元素,包括下标法和指针法。同时,讨论了指针与一维、二维数组的关系,强调数组名是常量指针。此外,文章还阐述了C语言中的动态存储分配机制,包括malloc()、calloc()、realloc()和free()函数的使用,以及动态分配数组的例子。最后,文章提供了一个动态分配数组并打印其内容的程序示例。
摘要由CSDN通过智能技术生成

指针的运算:针对这个我们直接上代码:

 1. 先来演示使用数组名来访问数组元素:

/*数组名访问数组元素*/
#include <stdio.h>
#define ARRAY_SIZE 6
int main(){
	int list[ARRAY_SIZE]={11,12,13,14,15,16};
	int i;
	for(i=0;i<ARRAY_SIZE;i++)
		printf("地址:%#p 值:%d 值:%d\n",(list+i),*(list+i),list[i]);
	return 0;
} 

        数组名list等价于数组首元素的地址&list[0], list为指向数组元素list[0]的指针。当一个指针指向数组中的某个元素时,可以对指针进行算术运算。因此,list+1等价于&list[1],list+1为指向小 数组元素 list[1]的指针;list+2等价于&list[2],list+2为指向数组元素list[2]的指针;list+i等价于&list[i],list+i为指向数组元素list[i] 的指针。
        可以通过下标法来访问数组元素:list[i]。也可以通过指针法来访问数组元素,list+i为指向数组元素list[i]的指针,使用解引用运算符“*”,*(list+i)就是list[i]。
程序第5行声明了整型数组list,第7、8行的for循环通过(list+i)输出数组元素的地址,通过*(list+i)和list[i]输出数组元素的值。

上面是通过数组名来访问数组元素,也可以通过指针变量来访问数组元素。

2.演示使用指针变量来访问数组元素:

/*指针变量访问数组元素*/
#include <stdio.h>
#define ARRAY_SIZE 6
int main(){
	int list[ARRAY_SIZE]={11,12,13,14,15,16};
	int *p=list;
	int i;
	for(i=0;i<ARRAY_SIZE;i++)
		printf("地址:%#p 地址:%#p 值:%d 值:%d 值:%d 值:%d\n",(list+i),(p+i),*(list+i),list[i],*(p+i),p[i]);
	return 0;	
}

程序第五行声明了整型数组list;第六行声明了整型指针变量p并指向list数组。

下面两行代码是等价的:

int *p=list;

int *p=&list[0];

数组名是数组首元素的地址。这样指针变量p就指向了数组元素list[0];

从上面的程序可见,使用指针变量也可以通过下标法或指针法来访问数组元素。p[i]=list[i](下标法),*(p+i)就是list[i](指针法)。同样,p+1是指向下一个元素的指针。

指针与一维数组:

对数组list中元素求和的程序代码:
 

#define ARRAY_SIZE 10;
int list[ARRAY_SIZE],sum,i;
...
sum=0;
for(i=0;i<ARRAY_SIZE;i++)
    sum+=list[i]; 

数组允许通过指针变量来访问数组元素,上面的程序代码改写如下:

#define ARRAY_SIZE 10;
int list[ARRAY_SIZE],sum,*p;
...
sum=0;
for(p=&list[0];p<=&list[ARRAY_SIZE-1];++p)
    sum+=*p; 


    
        在for循环中,指针p的初始值为数组list首元素的地址;每次执行循环时,p进行
自增操作,指向下一个数组元素。p先指向list[0];*p即为list[0],然后指向list[1];
*p即为list[1],以此类推,直至p指向最后一个元素list[ARRAY_SIZE-1],循环结束。

        数组名时数组首元素的地址,list等价于&list[0],list+ARRAY_SIZE-1等价于&list[ARRAY_SIZE-1]。


上面的程序代码可以进一步改写如下:

#define ARRAY_SIZE 10;
int list[ARRAY_SIZE],sum,*p;
...
sum=0;
for(p=list;p<=list+ARRAY_SIZE-1;++p)
    sum+=p;

 
    
上面的代码还可以写成:

#define ARRAY_SIZE 10;
int list[ARRAY_SIZE],sum,i,*p;
...
sum=0;
for(i=0,p=list;i<=ARRAY_SIZE-1;++1)
    sum+=p[i];


    
        指针和数组的关系是非常密切的,在处理数组元素时,既可以使用下标法,也可以采用指针法。

注意:数组名是一个常量指针,不能给数组名赋值。 在用指针处理数组元素时,经常会组合使用解引用运算符“* ”和自增运算符“++ ”。
         p=list;
        *p++=88;
由于后缀"*"的优先级高于"*",上述语句被视为:
        *(p++)=88;
也就是:
        *p=88;
        p++;
将88赋值给p所指向的数组元素list[0],然后p自增,指向下一个数组元素list[1]。

根据这种写法,上面的程序也可以写成:

#define ARRAY_SIZE 10;
int list[ARRAY_SIZE],sum,*p;
...
p=list;
sum=0;
while(p<=list+ARRAY_SIZE-1)
    sum+=*p++


假设p指向数组元素list[0],list[0]的当前值为88;
        (*p)++;
等价于:
        list[0]++;
list[0]的值加1,变成89。 

        当数组的元素类型为指针类型时,该数组就是一个指针数组。声明指针数组的一般形式如下:数据类型 *数组名[常量表达式] 
        数组名首先与后面的[]结合,表明是数组,再与数组的指针运算符"*"结合,说明数组的元素类型是指针类型。


 指针与二维数组:理清指针对二维数组中元素的访问。 

二维数组list的逻辑结构:


        数组名list表示数组第一行 list[0] 的地址 (&list[0]) , list+i 表示数组第i行 list[i] 的地址 (&list[i])。
list[0] 表示数组第一行首元素 list[0][0] 的地址 (&list[0][0])。list[i]表示数组第i行 list[i] 的地址(&list[i])。
list[0]+1 表示数组第一行第二个元素 list[0][1] 的地址 (&list[0][1])。list[i]+j 表示数组第i行第j列的地址 (&list[i][j])。*list([i]+j) 表示数组第i行第j列元素 (list[i][j])。 

下面我们来了解动态存储分配:

为了解决数组长度是固定的这一缺点,C语言提供与一种“动态存储分配”机制,使程序在运行过程中能根据需要分配内存空间。动态存储分配的内存空间通常称为堆。

为了动态存储分配内存空间,C语言提供了4个函数:malloc()函数、calloc()函数、realloc()函数和free()函数。使用这些函数时必须包含stdlib.h头文件。这几个函数在学数据结构时也会经常用到。

下面一一来介绍这几个函数:

malloc()函数:


void *malloc(size_t size);
malloc()函数分配指定大小(size个字节)的内存空间,但不对分配的内存空间进行初始化,并返回指向该内存空间的通用指针。
eg.    int *p;
    p=malloc(10 * sizeof(int));
分配了可以存放10个整数的内存空间。应该通过长度运算符sizeof来计算需要分配的内存空间大小,
而不要直接用整数,以免出现不必要的错误。
在赋值时,会把malloc()函数返回的通用指针(void*)自动转换为整型指针(int*)。
当然也可以明确使用强制类型转换。
eg.    p=(int *)malloc(10 * sizeof(int));
如果不能够成功分配指定大小的内存空间,malloc()函数会返回空指针NULL。
可以使用如下方式测试malloc()函数的返回值:
p=(int *)malloc(10 * sizeof(int));
if(o==NULL){
    printf("malloc函数分配失败!\n");
    exit(EXIT_FALLURE); 

calloc()函数:


void *calloc(size_t nmemb,size_t size);
分配指定大小(nmemb * size字节)的内存空间,对分配的内存空间进行初始化,并返回指定该内存空间的通用指针。
如果不能够成功分配指定大小的内存空间,calloc()函数会返回空指针NULL。
eg.        p=(int *)calloc(10,sizeof(int));
if(p==NULL){
    printf("calloc函数分配失败!\n");
    exit(EXIT_FALLURE);

malloc函数最常用。因为malloc()函数不对分配的内存空间进行初始化,因此比calloc()函数更高效。


realloc()函数:


void *realloc(void *ptr,size_t size);
调整先前分配的内存空间大小,并返回指向该内存空间的通用指针。
指针ptr指向先前由malloc()、calloc()或realloc()分配的内存空间,
size表示新内存空间大小(大于或小于原有内存空间大小)。
如果不能够成功调整先去分配的内存空间大小,realloc()函数会返回空指针NULL,先前内存
空间中的数据不会发生改变。
eg.        
int *q;
q=(int *)realloc(p,20 * sizeof(int));
if(q==NULL){
    printf("realloc函数调整失败!\n");
    exit(EXIT_FALLURE); 

如果realloc()函数的第一个参数为空指针NULL,其功能就像malloc()函数一样。
eg.
p=(int *)realloc(NULL,10 * sizeof(int));
等价于:
p=(int *)malloc(10 *sizeof(int));
如果realloc()函数的第二个参数是0,释放先前分配的内存空间。
eg.
realloc(p,0);
释放指针p所指向的内存空间。 


free()函数:


void free(void *ptr);
free()函数释放先前由malloc()函数或calloc()函数分配的内存空间。指针ptr指向要释放的内存空间。
eg.
int *p=(int *)malloc(sizeof(int));
int *q=(int *)malloc(sizeof(int));
指针p和q分别指向各自的动态存储分配的内存空间。
p=q;
把q赋值给p后,指针p和q都指向同一个内存空间。
现在没有指针指向原来指针p指向的内存空间,该内存空间就无法访问了。这种无法再访问到的内存空间称为垃圾。
程序中如果留有垃圾,往往会发生内存泄露问题。动态存储分配的内存空间一旦使用完毕应立即释放。
因此应该在q赋值给p之前,释放不再需要的内存空间。
eg.
free(p);
p=q;
调用free()函数释放指针p所指向的内存空间。此内存空间被释放后,可以重新分配使用。

最后来演示动态存储分配数组:

/*动态存储分配数组*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void printArray(const int list[],int arraySize);
int main(){
	int i,arraySize;
	int *array;
	printf("请输入数组元素个数:");
	scanf("%d",&arraySize);
	array=(int *)malloc(arraySize * sizeof(int));
	if(array==NULL){
		printf("malloc()函数分配失败!\n");
		exit(EXIT_FAILURE);
	}
	srand(time(NULL));
	for(i=0;i<arraySize;i++)
		array[i]=rand()%100;
	printArray(array,arraySize);
	free(array);
	return 0;
}
void printArray(const int list[],int arraySize){
	int i;
	for(i=0;i<arraySize-1;i++)
		printf("%d ",list[i]);
	printf("%d\n",list[arraySize-1]);

}

  

 每次运行的结果可能不同。

程序第6~22行是main()函数,第23~28行是printArray()函数。
在main()函数中,第8行声明了整型指针变量array,要使用动态存储分配首先要声明指针变量;  第10行从键盘输入需要的数组长度并存放在变量arraySize中;                                                      第11行动态存储分配数组长度为arraySize的数组 array,它可以容纳 arraySize个整数;一旦array指向动态存储分配的内存空间,就可以把array视为数组名;                                                          第16行使用当前时间初始化随机数“种子”值;                                                                                 第17、18行产生arraySize个0~99范围内的随机数并存放在数组array中;                                    第19行调用printArray()函数输出数组array的值;第20行释放array所指向的内存空间。

 

有关指针与数组的笔记就分享到这啦!若对小伙伴们有帮助的话请留个👍哇!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

تچ快乐杂货店يچ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值