C语言的核心就是操作内存的方式和方法。
指针其实就是内存资源的地址或门牌号。
指针变量,存放指针这个概念的盒子。
指针两个属性,1、存放的盒子需要多大呢?2、存放在盒子里的所指向内存地址的读取方法。地址在一定程度上就是指资源
一般32Bit系统中,指针就是4个字节。用*读取。
const char *p;//const修饰*,则指针指向的内容是尽量不要修改。比较典型的是就是指向字符串。
char *const p;//const修饰P,则地址是不可以变的。类似于硬件资源的地址,但地址上的值是可以变的。
const char *const p;//更严格,类似于硬件ROM。
指针的加法或减法运算,都属于一个单位进行的操作,一个单位指sizeof(p[0])
变量名+「」;//如P「0」;P+1;P+2;P指的地址,此种形式是地址内容的标签访问方式。p+n==P[n]
指针的逻辑运算主要是==和!=。并且指针必须是同类型的值的比较。地址有没有是无效的状态 ==NULL
注:c 更关注的是内存,而其他面向对象的语言更多关注的是事物以及之间的关系。
多级指针:存放地址的地址的盒子(其实是一个地址表)。更多的描述的是内存之间的关系。
数组就是一个空间,空间的赋值只有按照标签逐一处理一种方式,如 int a[10]={0};//此种方式往往需要库函数的调用。
strcpy()这个是严格按照字符串拷贝,不到’/0‘不会停,所以很容易内存泄漏。并且看到0就会停止。
memcpy(dest,src,n)//n代表的是最小的单位,字节,n的位置都是n*sizeof(dest数据类型)。
指针与数组间相互赋值要看读内存的方法是不是一致。如:int a[10];int *p=a;//根据从右往左结合,P就是指向int的一个地址,而a是一个数组首地址,a与p读内存地方式是相同的,没有问题。
int b[2][3];int **p1=b;//这样就不可以,b的读取方式是一行一行的读,而p1是一个指向int型指针的指针,还是读一个地址,可以这样int(*p1)[3]=b;//p1是一个指针,指向3个int 型的数组。
结构体的大小一定是4的倍数,成员变量的顺序不同,会造成对齐时,最终的大小也不一样。
内存分布图:从低地址到高依次是:代码段(只读数据段,全局数据空间)是静态空间+运行时的堆malloc+?空间+内核
只读数据段:系统保护此段的数据,不让操作。是静态空间,在编译时就存在,消失时整个程序结束时消失
栈空间,函数运行时
堆空间,是程序员分配,释放 最好是配对使用。