C语言:指针4(常量指针和指针常量及动态内存分配) ...

打印 上一主题 下一主题

主题 773|帖子 773|积分 2319

常量指针与指针常量

常量:分为字面量和只读常量,字面量就是我们平时直接操作的量:
printf("%d\n",12);/printf("%s\n","hello");只读常量使用关键字 const 修饰,凡是被这个关键字修饰 的变量,一旦赋值,值就不能改变。
语法:
  1. // 字面量
  2. printf("%d\n",12);
  3. // 只读常量
  4. const int a = 10;
  5. a = 21;// 编译错误,因为此时这个变量是只读常量,所以不可更改其值
复制代码
常量指针

界说:常量的指针,本质是一个指针,指针指向的数据不能改变。
界说格式:
  1. const 数据类型 *变量名;
复制代码
举例:
  1. const int *p;// p就是常量指针
复制代码
结论
1. 常量指针指向的数据不能被改变(不能解引用间接修改数据)
2. 常量指针的地址可以改变(指向是可以改变)。
应用场景:作为形式参数,实际参数需要给一个常量。
  1. void foreach(const int *array,const int len){..}
复制代码
案例:
  1. #include <stdio.h>
  2. int main(int argc,char *argv[])
  3. {
  4.     // 定义变量
  5.     int a = 10;
  6.     // 定义常量指针
  7.     const int *p = &a;
  8.     //*p = 100;// 编译报错,常量的值不能被改变
  9.     printf("%d\n",*p);// 10
  10.     // 定义变量
  11.     int b = 20;
  12.     p = &b;    // 编译通过,常量的地址可以被改变
  13.     printf("%d\n",*p);// 20
  14.     return 0;
  15. }
复制代码
指针常量

界说:指针的常量,指针的指向不能改变
界说格式:
  1. 数据类型* const 变量名;
复制代码
举例:
  1. int* const p;// 指针常量
复制代码
结论:
1. 指针常量的指向不能改变(不能给指针变量重新赋地址值)
2. 指针常量的指向的数据可以改变。
留意:指针常量在界说时就要赋值;不能先界说后赋值,否则编译报错
案例:
  1. #include <stdio.h>
  2. int main(int argc,char *argv[])
  3. {
  4.     // 定义变量
  5.     int a = 10;
  6.     // 定义指针常量
  7.     int* const p = &a;
  8.     *p = 100;// 编译通过,常量的值可以被改变
  9.     printf("%d\n",*p);// 100
  10.     // 定义变量
  11.     int b = 20;
  12.     //p = &b;   // 编译报错,常量的地址不可被改变
  13.     printf("%d\n",*p);// 100
  14.     return 0;
  15. }
复制代码
常量指针常量

界说语法:
  1. const 数据类型* const 变量名;
复制代码
举例:
  1. const int* const p;
复制代码
作用:p的指向不能被改变(地址不可更改),p指向的数据不能改变(地址对应的数据不可更改)
动态内存分配

我们要想实现动态内存分配,就需要学习标准C提供的函数库(API):
1. 函数所属的库文件
2. 函数的原型-函数的声明
        函数名
        形参
        返回值范例
3. 函数功能
留意:内存分配函数在申请内存时,建议用多少申请多少,可以有少量的预留量;但不能越界访问
(固然编译和运行不报错,但是数据不安全(野指针))
常用函数

malloc

头文件: #include <stdlib.h>
函数功能:C库函数 void* malloc(size_t size); 分配所需的内容空间,并返回一个指向它的
指针。
函数原型:
函数名:malloc
形式参数:size_t size:需要申请的内存块的大小,以字节为单位。本质上是一个 unsigned
long int
返回值范例:void*(万能指针):该函数返回一个指针,指向已分配大小的内存,如果请
求失败,返回NULL(0x000000000000对应的一块不可访问的区域)
举例:
  1. int* p = (int*)malloc(sizeof(int));
  2. // 清零,这里不是释放内存,只是将内存中的随机值清理掉
  3. bzero(p,sizeof(int));
  4. // 使用空间...
  5. // 释放空间
  6. free(p);
复制代码
说明:
malloc函数分配的内存没有默认值,内存中的数据是随机值(大概率是0),使用前需要借
助于bzero()清零。
malloc函数申请的内存空间连续
calloc

头文件: #include <stdlib.h>
函数功能:C库函数 void* calloc(size_t nitems,size_t size) 分配所需的内存空间,并返回
一个指向它的指针。
malloc和calloc之间的区别:malloc不会设置内存为零,需要使用bzero()清零,而calloc会设置内
存为零。
函数原型:
函数名:calloc
形式参数:
size_t nitems:申请多少个
size_t size:一个占几个内存单位(1个内存单位=1个字节)
返回值范例:void*:该函数返回一个指针,指向已分配大小的内存,如果请求失败,返回
NULL
举例:
  1. int *p = (int*)calloc(1,sizeof(int));  
  2. // 使用空间...
  3. // 释放空间
  4. free(p);
复制代码
说明:
calloc函数分配的内存有默认值,每个内存单位都是0
calloc函数申请的内存空间连续
calloc大多时候为数组中的元素申请内存
案例:
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. /**
  4. * 需求:转存栈中数组中的数据
  5. */
  6. int main(int argc,char *argv[])
  7. {
  8.     // 在栈区创建一个数组
  9.     int arr[3] = {11,22,33};
  10.     // 在堆区申请内存
  11.     int *p = (int*)calloc(3,sizeof(int));
  12.     // 转存
  13.     for(int i = 0; i < 3; i++)
  14.         p[i] = arr[i];
  15.     // 遍历堆中数据
  16.     for(int i = 0; i < 3; i++)
  17.         printf("%-4d",p[i]);
  18.    
  19.     printf("\n");
  20. // 在堆中申请空间,使用完毕一定要记得释放
  21.     free(p);
  22.     p = NULL;
  23.     printf("p=%p\n",p);
  24.     return 0;
  25. }
复制代码
realloc

头文件: #include <stdlib.h>
函数功能:尝试重新调整之前调用malloc或calloc所分配的ptr所指向的内存块的大小。
函数原型: void *realloc(void *ptr,size_t size)
函数名:realloc
形式参数:
void *ptr:是malloc大概calloc的返回值
size_t size:重新分配后的内存大小
返回值:void*:该函数返回一个指针,指向已分配大小的内存。如果请求失败,返回
NULL。
案例:
  1. int *p = (int*)malloc(4);
  2. int *w = (int*)realloc(p,20);
  3. // int *q = (int*)realloc(p,0); // 等效于free(p)
复制代码
说明:
1. realloc以原来malloc返回的内存地址开始,分配总共20个字节的内存空间
2. 如果原来的内存空间后有20个连续空间,就扩容20-4 =16个内存单位,返回原来旧的内存首
地址。
3. 如果原来的内存空间后不敷20个连续内存空间,就重新找一个内存地址开始,申请20个内
存单位。并将原来的数据拷贝到新的内存中,回收旧的内存单位,并返回新的内存首地址。
free

头文件: #include <stdlib.h>
函数功能:释放之前调用 malloc、calloc、realloc所分配的内存空间,是访问完记得使用NULL
置空。
函数原型: void free(void *ptr)
函数名:free
形式参数:
void *ptr:calloc,malloc.realloc的返回值
返回值范例:void:没有返回值
留意:
1. 堆内存中的指针才需要回收,栈中系统会自动回收
2. 堆内存不能重复回收,运行会报错
说明:
1. 堆的内存空间相比较栈要大许多
2. 内存分配函数返回的指针变量可以参与运算(只读),但不能被修改(p++大概p+=i 是错误
的)


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

tsx81429

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表