-------------------------------------------指针操作-----------------------------------------------------------
·指针变量:是一种记录地址的变量(相应类型变量: char int float...)
·定义:
类型名 * 变量名 ----> 所装载地址上对应的变量类型 ----> 通过声明 * 标识指针
E.g:
int A = 5;
int *pA = &A; ---> pA 记录变量 A的地址,*pA在声明处表示地址
pA -----> 在进行指针运算时,不用加* ,表示地址
*pA -----> 获取该指针对应的变量的值,即*pA = 5
·指针初始化:
1) 定义时初始化: int A = 5 ; int *pA = &A;
2) 先定义后初始化: int A ; int *pA ; pA = &A;
指针也是变量,那么指针变量也是有大小的。在当前32位系统中,CPU寻址大小32位,即4字节
·指针运算:
★指针参与运算时,增减的大小为其所对应的数据类型的单元大小。
int *pA = &A; pA + 1 -----> A地址上偏移4个字节,因为int占4个字节
应用:通过指针可以访问当前地址前后内存上的数据。
-----------------------------------------------数组----------------------------------------------------
·数组是具有相同类型数据的组合。
int A,B,C; ---> 定义了三个整型元素;
int arryA[3]; ----> 定义了一个整型数组,里面有3个同类型成员;-----> 一维数组
特殊情况下:根据内存对齐或者内存管理的因素,第一种情况所分配的数据存储空间可以不连续。第二种情况所分配的数据存储空间必须连续。(就像是3个人去饭馆吃饭,第一种情况可能3人不坐在一起,而第二种情况3人必须坐在一起)
★找到数组的首元素地址,即可访问全部数组的数据。
·数组初始化:
1)定义时可进行整体初始化 :int a[10] = {1,2,3,4}; 表示a[0],a[1],a[2,a[3]分别赋值1,2,3,4,a[4]~a[9]未完成赋值的元素,系统自动赋0
2)定义后,需逐个赋值: a[0] = 1; a[1] = 2; a[2] = 3; a[3] = 4;
数组元素的访问,从下标为0开始 ----> 一般情况下,可以越界读取数据(主要看内存的访问权限)
·数组与指针的关系:
数组名等价与数组首元素的地址 -----> 数组名指向当前数组存储空间的地址
E.g:
int arryA[10]={1,2…};
&arryA[0]就相当于对arryA数组的寻址
·指针访问数组:
*(pA+ 1) = pA[1]
Demo:
int arryA[10] = {1,2};
int *pA = arryA;
*(pA + 1) = 100;
等价于:
pA[1] = 100;
------------------------------------------------二维数组------------------------------------------------
int arryB[3][4]; arryB[0][0] arryB[0][1] arryB[0][2] arryB[0][3]
arryB[1][0] arryB[1][1] arryB[1][2] arryB[1][3]
arryB[2][0] arryB[2][1] arryB[2][2] arryB[2][3]
arryB :3行4列共12个 int 元素
·二维数组在内存中,也是连续存储;
---------------------------------------- 一维数组与指针 -----------------------------------------------
字符数组定义:
1)char arryC[10] = {0xFF,0xF1,…}; ---> 整数赋值,对应于ascii码表
2)char arryC[10] = "hello"; ---> 使用字符串常量对数组赋值 ----> "hello" 字符串,系统自动添加'\0' --> 字符串结束符总长度: 5+1=6
3)char arryC[10] = {'h','e','l','l','o','\0'} ;
·在C语言中,"..." 字符串常量 'A' 字符常量
E.g:
char *pC = ; ----> char *pC = &arryC[0]; ----> char *pC = arryC;
所以有:
scanf("%s",pC);等价于
scanf("%s",arryC);
--------------------------------------- 二维数组与指针 --------------------------------------------
E.g:
设:int arryC[3][4] = {"ABC","BCD","CDE"};
在Linux中断下可看到
(gdb) p arryC
$1 = {"ABC", "BCD", "CDE"}
(gdb) p pC
$2 = (char (*)[4]) 0xbffff30c
(gdb) p &arryC[0]
$3 = (char (*)[4]) 0xbffff30c
可以看到 pC 与 arryC[0]是同一类型指针,且指向的是同一地址
(gdb) p arryC[0]
$4 = "ABC"
(gdb) p *&arryC[0] -----------------> int A ; *&A ----> A(相当与取逆反操作)
$5 = "ABC"
(gdb) p *pC -----> 等价于 arryC[0] ----> 一维数组 ---> char *
$6 = "ABC
(gdb) p *(pC+1)
$14 = "BCD"
(gdb) p pC[0]
$15 = "ABC"
(gdb) p pC[1]
$16 = "BCD"
·二维数组指针?
char (*p)[4] -----> 数组指针 ----> 指向数组地址的指针(存放数组地址)
char *p[4] -----> 指针数组 ----> 每个成员都是指针
char (*p)[4]
char (*p)[4] ---> 二维数组数组名
char arryD[10];
设有char *p[4]
p[0] ----> 类型 char * ===> 一维字符数组名 ====> p[0] = arryD;
char arryE[3][4]; --------> arryE[0] arryE[1] arryE[2] ---> 成员为一维数组
char *pE[3] --------> pE[0] = arryE[0]
类型分别为----> char * char *
★ 指针定义后必须准确赋值初始化才可使用,否则成为野指针。
----------------------------------------二级指针-----------------------------------------
char *(*p); -----> 存放指针地址的变量
char A;
char *pA = &A;
char **ppA = &pA;
char *pE[3];
char **ppE = pE;
char A[5];
char *pA = A;
//替换分析
*(pA+1) == A[1] == char === pA[1]
//替换分析
*(ppE+1) == ppE[1] == char * === pE[1]
---------------------------------------指针函数与函数指针----------------------------------------------
指针函数 -----> 返回值为指针的函数
函数指针 -----> 指向函数的指针 -----> 存放函数地址的指针
E.g:
int add(int x ,int y) ----> 整型函数
{
return x+y;
}
//指针函数 -----> 在函数体内开辟一段内存空间,然后返回该内存空间的地址。
// -----> 调用系统中分配内存的函数,完成空间申请
// -----> malloc && free
// void *malloc(size_t size); ----> 堆内存,手动分配,手动释放----不释放导致内存泄漏
// void free(void *ptr);
char* alloc_xx(int size) ----> 整型指针函数 ----> 返回值为整型指针
{
char *p;
p = (char *)malloc(size); ----> 分配内存 ----> 记得使用完毕后释放内存!!!!!
return p;
}
free(p);
void * ----> 空类型指针,当分配的空间不知道采用何种数据类型操作时,是辅助指针运算使用的。如果已经明确分配的地址空间存放的数据类型,则需要类型转换。
//函数指针 ----> 在原始的函数类型声明的基础上,增加(*p) ---> 声明为指针类型
文章评论(0条评论)
登录后参与讨论