一:认识下内存四区
栈区:系统自动开辟,释放。(定义变量,根据作用域开辟或释放内存)
堆区:程序员主动开辟释放。在头文件stdlib.h里面,malloc(),free()分别是开辟空间和释放空间
全局区:全局静态变量
代码区:保存代码
二:地址
把内存(内存条)以字节为单位,编号,地址是唯一的 是一种数据
& 取址符 单目运算符 右结合性 作用是返回一个变量的地址
首地址:这个数据的第一个存储单元的地址
三:指针变量
指针变量来存储地址。
定义一个指针:
int main(){
int a; //整形变量
int *p; //指向整形的指针
pa = &a;
return 0;
}
指针类型 *变量名
数据类型:这个指针变量指向的类型
* :星号只是说明这里是一个指针变量,标记。
变量名 :通常p的前缀 pointer
对指针赋值
初始化:定义的时候直接赋值
int a;
int *pa = &a;
赋值:先定义,再赋值
指针的引用:
指针变量自己的值:pa
指针变量指向的值: *pa
(星号:在定义指针变量的时候,*取表示,说明定义指针变量。
*的前面没有数据类型,她是一个运算符 取值运算符 取某一个指针指向的值)
函数调用的时候:只是把实参的值传递给形参,在函数中形参的变化并不影响实参
四:野指针
没有明确指向的指针。很危险,不确定指向的地址有没有被使用
明确的知道这个指针会不会产生不必要的麻烦,如果会,则在定义的时候 int *p = NULL;
五:空指针
不确定类型的指针(地址)。
void*
void* malloc(4); //开辟4个字节的空间
void*类型 可以强制转换成其他任意类型 (int*)malloc(4); (char(*)[4]malloc(4);
注意:类型的大小
六:指针的运算
指针的运算其实就是地址的偏移(+ - ++ --)。两个地址之间的运算是没有意义的(比如天安门的地址+圆明园的地址等于?)。
int *p
p+1;
p+2
p-1;
p++;
p--;
+ - p的指向是不会动的
++ -- p的指向是会动的
p+1; //p 1000 p+1 = 1001? 不一定 跟指向的类型有关系。指针的偏移总是以这个指针所指向的数据的大小来偏移的
举例:
#include <stdio.h>
int main()
{
char a;
char *pa = &a;
int b;
int *pb = &b;
int c[10];
int (*pc)[10] = &c;
printf("pa = %d,pa+1 = %d\n",pa,pa+1);
printf("pb = %d,pb+1 = %d\n",pb,pb+1);
printf("pc = %d,pc+1 = %d\n",pc,pc+1);
return 0;
}
执行结果为:
pa = 1365882871,pa+1 = 1365882872 pb = 1365882864,pb+1 = 1365882868 pc = 1365882816,pc+1 = 1365882856
七:一维数组与指针
&a是指向整个数组的指针。
a是数组名:【数组名是这个数组的首地址】
int *p1 = a;
int (*p2)[5] = &a;
a指向数组的第一个存储单元 a[0]
访问数组元素:
数组名:*(a+m) // a[m]
指针:int *
int a[5] = {1,2,3,4,5};
int *pa =a; //pa =&a[0];
for(i=0;i<5;i++)
{
printf("%d\t",*(pa+i)); //pa不变化
}
for(i=0;i<5;i++)
{
printf("%d\t",*(pa++)); //改变了pa的指向
}
总结:a *(a+0) *(a+1) ..... *(a+m) 就是a[m]
pa *(pa+0) *(pa+1) ........*(pa+m) 就是pa[m]
八:二维数组
假设int a[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};
在内存中是连续存储的,本质上是由三个一维数组组成的,分别是a[0],a[1],a[2];
内存分布为:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
a[0] a[1] a[2]
a+0 a +1 a+2
*(a+0)
a[0] 一维数组名
这个数组名是a,指向数组的【第一个存储单元】,如果是二维数组,那么第一个存储单元就是指一维数组,
访问m行n列:
*(*(a+m) +n) 值
九:多维数组和指针
8维数组
k b c d e f g h
*(*(*(*(*(*(*(*a+k)+b)+c)+d)+e)+f)+g)+h)
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
*(a+m)
*(*(a+m)+n)
*( *(*(a+m)+n)+k)
备注:此笔记由观看学习B站博主会编程的小家伙的视频《彻底搞定C语言指针详细完整版-初学者必备》所记,感谢这位老师,侵权删。