C语言指针内存管理的学习文档

C的详细学习

内存管理

1.register
a)将变量存储到寄存器中
b)优点:操作速度快,编译器将变量a直接放入寄存器里面,以提高读取速度
c)缺点:寄存器数量有限
2.Const
a)只读,值不变,依然在内存;
b)修饰普通话变量,不可修改;
c)修饰数组,其元素不改;
d)修饰指针,修饰p,对象只读,指针的指向可变,修饰p,对象可变,指针的指向不变。指针指向不变,内容不变。
3.动态内存管理
a)标准库(stdlib.h)提供以下四个函数用于动态内存管理。当程序在具有更多内存的系统上需要处理更多数据时,不需要重写程序。
b)malloc() 、 calloc()
i.分配新的内存区域
c)realloc() 调整已分配的内存区域
d)Free() 释放已分配的内存区域
e)对象在内存中所占空间的大小是以字节数量为单位计算的,定义了类型size_t用来保存这种内存空间的相关信息。sizeof运算符以类型size_t返回字节数量。
4.动态内存分配
a)void
malloc(size_t size);
b)函数 malloc()分配连续的内存区域,其大小不小于size,程序获得内存区域时,内存中的内容尚未决定。
c)void*calloc(size_t count,size_t size);
d)函数 calloc()分配一块内存区域,其大小至少是count_size,容纳一个具有count个元素的数组,每个元素占用size个字节,calloc()会把内存中每个字节都初始化为0。
e)两函数都返回void指针,这种指针被称为无类型指针,返回指针的值是所分配内存区域中的第一个字节的地址,分配内存失败时,返回空指针。
f)void *alloca(size_t size) 栈内动态分配
5.内存映射
a)mmap/munmap
b)mmap可以将一切的文件映射至内存,文件被映射到多个页上,如果文件的大小不是所有页的大小之和,最后一个页不被使用的空间将会清零。Munmap执行相反的操作,删除特定地址区域的对象映射。
c)寄存器虚拟地址 = 寄存器物理地址 + 基地址
d)Linux一切皆文件
6.volatite
a)作用:用来修饰被不同线程访问和修改的变量,在原子操作中也有应用。没有它,多线程程序可能出现不可预期的错误,也可能因为编译器的各种优化而导致编译后的结果表达了不同的意思,使程序出现难以发现的错误。
b)编译器每次都从该变量的原始地址处重新读取该变量的值,使得取到的值总是“最新”的。如果编译器在编译涉及到访问某个变量的值的时候,它会把频繁访问的变量保存到CPU的寄存器中供复用,以加快再次访问变量的速度。但是该值是从CPU的寄存器中取出的,它虽然是最原始的值,但如果在其他时间,其他地点的程序如果修改了该变量的值,那么编译器拿到的值就是一个“过时”的值,这样就会出现错误,其他时间可以是CPU的线程调度,其他地点可以是另一个线程的代码。

高级类型定义

1.不带参数的宏定义
a)#define 标识符 字符串;
2.带参数的宏定义
a)#define 宏名(参数表) 字符串
3.为了与变量名相区别,通常用大写字母表示宏名;

指针详细学习

1.表示指向,返回指针所指变量的值。
2.变量的地址可以使用地址运算符&求得,&i表示变量i的地址,ip=&i;
3.指针变量和其他普通变量一样代表内存中的一个存储单元,只是在此存储单元中只能存放“指向”被访问对象的地址,所以也把指针变量简称指针,把指针指向的对象称为目标或目标变量。目标或目标变量可以用指针变量名前面加上
表示。
a)Eg: int ip,i;
ip = &i;
ip = 3;
4.运算符与&运算符的优先级相同,并且都是右结合。&i = i;
5.为避免出现未初始化的指针,将指针初始化为NULL值。char cp = NULL;
6.getch()这个函数是一个不回显函数,当用户按下某个字符时,函数自动读取,无需按回车。所在头文件:conio。
7.取地址运算&
8.取内容运算

9.数组赋值的时候,是赋值的数组首地址;
10.指针变量加减一个整数n的运算,并不是指针变量的地址值加减一个整数n,而是将指针由当前所指向的位置向后向前移动n个数据位置,即指向其基本类型的后n个或前n个元素。
11.在对指针进行加减运算中,数字1不在代表十进制的整数,而是代表一个存储单元的长度,其长度占多少字节数是根据指针的类型确定的。
12.如果p是一个指针,n是一个正整数,则进行p+n运算后的实际地址是:P+=n
sizeof(数据类型)
13.指针变量的相减运算,指向同一数组的两个指针变量可以相减,其差表示这两个指针变量所指数组元素之间相差元素个数。(两指针的地址值之差)/(一个数据项的存储字节数)
14.若两个指针指向同一个数组的元素,则指向前面元素的指针变量小于指向后面元素的指针变量。
15.大于,小于用于比较两指针所指向的地址大小关系,== ,!=用于判断两指针是否指向同一个地址。
16.数组被存放在一段连续的内存单元中,对数组元素的访问是通过数组元素的下标来实现的。
17.int a[10] = {0,1,2,3,4,5,6,7,8,9},k,p;
p = a;
For(k = 0 ; k < 10 ; k++)
Printf(“%d”,
(p+k)); (p+k)与(a+k)等价
18.的优先级高于+的优先级
19.通过指针访问数组元素,通常是通过循环语句进行循环移动来实现的
20.P+i,a+i 表示a[i]的地址,指向数组的第i个元素;
21.
(p+i),
(a+i)所指对象的内容,即a[i]
22.p[i] 表示*(p+i),即通过带下标的指针引用数组元素
23.数组名代表的是数组的首地址,是一个地址常量,因此a++,a=p,a+=i都是非法的;
24.指针是一个变量,可以对其进行自加,自减和赋值运算,p++,p=a,p=&a[i]
25.a和a[0]具有不同含义,a是一个地址常量,a[0]的地址,a[0]是一个数组元素,代表存放数据的存储单元。
26.指针不指向同一数组,比较无意义。
27.&a[i][j] = a[i]+j; (a+i)+j;
28.&a[i][0] = a[i] ,
(a+i);
29.二维数组咋内存中是按照内存中按行优先连续存放的,因此利用数组元素的指针可以访问二维数组的各元素,数组的长度可以是任意的。
30.Int a[3][4]
*(a[i]+j)
*(a(a+i)+j)
31.一个指针变量中只能存放一个指针值,要同时保存多个地址值就需要使用多个指针变量,把这些指针变量的值放在一个数组中,就形成了指针数组。因此指针数组是指数组中每一个元素都是指针的数组,这些指针是指相同数据类型的变量。
32.[]的优先级高于

33.Strcmp(),字符串的比较,等于返回0,小于返回负数,大于返回正数。
34.在二维数组的处理中,常常使用指向由n个元素组成的一维数组的指针,定义为:类型标识符 (指针名)[常量表达式],指向一维数组的指针只能访问固定长度的数组。
35.P的增量是以一维数组为单位。
36.通过指向由n个元素组成的一维数组的指针p引用a[i][j]
i.
(a[i]+j) *(p[i]+j)
ii.a[i][j] p[i][j]
37.用字符数组表示字符串和用字符指针表示字符串的区别:
38.数组名是一个地址常量,不能重新赋值。
i.Char str[] = “The string”;
39.可以将一个字符串常量赋给一个字符指针变量。
i.Char *str = “str”;
ii.C语言把一个字符串常量隐含地处理成一个字符型一维数组,由str指向它的首地址。
40.指向指针的指针 类型标识符 **指针变量名 第一个指针的值是第2个指针的地址
41.指针运算时右结合的
42.在程序中一旦定义了变量和数组,c编译程序就会为这些变量或数组分配相应的存储空间,即使这些变量或数组在程序运行期间不在使用,也必须占有这些固定的存储空间,不能另做它用,直到程序结束,才能释放变量和数组所占的存储空间,通常把这种预先确定存储空间,并且在程序运行期间存储空间的大小固定不变的分配方法,称为静态存储分配。
43.为了解决静态存储分配可能出现的内存不够或浪费的现象,在c语言中采用了动态存储分配技术,即在程序执行过程中根据需要临时分配存储空间,不需要时可以随时释放这些存储空间。
44.Void *malloc(unsigned size)
a)函数的功能是在内存中分配一个指定长度的存储空间,以字节为单位,函数返回指向分配的存储区起始地址的指针。如果不能获得所需的存储空间,函数返回值为NULL;
b)p = (int *)malloc(10);
c)或者p=(int )malloc(sizeof(int))
45.free()函数
a)Void free(void prt)
b)函数的功能是释放由prt所指向的内存空间,以便这些内存空间可在分配使用,用以释放malloc()/calloc()/realloc()分配的存储空间。
46.calloc()函数
a)Void calloc(unsigned num,unsigned size)
b)函数的功能是在内存中分配一块连续的容量为num
size的存储空间,num为需要分配的元素个数,size为每个元素所占的内存空间,以字节为单位。函数返回一个指向被分配内存的指针,如果不能获得所需存储空间,函数返回值为NULL;
47.指针就是地址,地址就是指针
a)32位系统下任何指针类型都是4字节;
b)64位系统下任何指针类型都是8字节;
c)直接操作内存,效率高;
48.数组
a)数组本质就是一个指针常量
b)a[b]——>
(a+b)
49.void
类型指针
a)void *类型指针可以接收任意类型指针
b)Int memcmp(const void *s1,const void s2)
c)不能对void
类型指针引用赋值
d)int var = 0;void ptr = &var; (X),无法判断void类型,所以无法对ptr赋值。
50.二级指针
a)二级指针用于操作一级指针,常用于传参,想要在函数中改变变量的值,必须传入地址。
51.指针数组
a)用来存放指针的数组
i.char *a[n]
b)数组存储类型为char *型指针,本质上是数组
i.char var = 0 ; char *a[] {&var,”hello”};
ii.字符串本质上是一个指向首字母的指针常量。
52.数组指针
a)指向数组的指针
i.char (*a)[]
b)本质上是一个指针,指向类型是数组
i.char a[10] = “hello”;
ii.Char(*p)[] = &a;
iii.char *q = a;
53.函数指针
a)函数名本身就是地址常量;
b)指向函数的指针叫做函数指针;
c)利用这一特性,可以实现hook机制,CPU执行某一条指令的时候,我们可以把这条指令执行到自己的东西,执行完自己的东西要不要继续执行原有的由你决定,一般是hook替换跳转命令。
54.常见错误
55.使用野指针(没有具体指向的指针)
i.解决:定义指针时初始化,安全使用先判空
56.内存访问过界
i.解决:使用安全函数,编码规范
57.内存泄漏
i.malloc类函数和free成对使用
58.使用非法内存
i.使用前查看指针指向内存区域
ii.谨慎使用alloca类函数
59.c的运算符优先级

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值