铁律1:指针是一种数据类型
指针也是一种变量,占有内存空间,用来保存内存地址
测试指针变量占有内存空间大小
2)*p操作内存
在指针声明时,*号表示所声明的变量为指针
在指针使用时,*号表示 操作 指针所指向的内存空间中的值
*p相当于通过地址(p变量的值)找到一块内存;然后操作内存
*p放在等号的左边赋值(给内存赋值)
*p放在等号的右边取值(从内存获取值)
3)指针变量和它指向的内存块是两个不同的概念
//含义1 给p赋值p=0x1111; 只会改变指针变量值,不会改变所指的内容;p = p +1; //p++
//含义2 给*p赋值*p=’a’; 不会改变指针变量的值,只会改变所指的内存块的值
//含义3 =左边*p 表示 给内存赋值, =右边*p 表示取值 含义不同切结!
//含义4 =左边char *p
//含义5 保证所指的内存块能修改
int a = 10;
char *p1 = 100; //分配4个字节的内存
char ****p2 = 100;
int *p3 = NULL;
p3 = &a;
*p3 = 20; //间接的修改a的值
//'*'就像一把钥匙 通过一个地址(&a),去修改a变量的标示的内存空间
{
int c = 0;
c = *p3; //c=20
//*p放在=号左边 写内存
//*p放=号的右边 读内存
printf("c:%d \n", c);
}
4)指针是一种数据类型,是指它指向的内存空间的数据类型
含义1:指针步长(p++),根据所致内存空间的数据类型来确定
p++=——>(unsigned char )p+sizeof(a);
结论:指针的步长,根据所指内存空间类型来定。
注意:建立指针指向谁,就把把谁的地址赋值给指针。图和代码和二为一。 不断的给指针变量赋值,就是不断的改变指针变量(和所指向内存空间没有任何关系)。
铁律2:间接赋值(*p)是指针存在的最大意义
1)两码事:指针变量和它指向的内存块变量
2)条件反射:指针指向某个变量,就是把某个变量地址否给指针
3)*p间接赋值成立条件:3个条件
a)2个变量(通常一个实参,一个形参)
b) 建立关系,实参取地址赋给形参指针
c) *p形参去间接修改实参的值
Int iNum = 0; //实参
int *p = NULL;
p = &iNum;
iNum = 1;
p =2 ; //通过形参 == 间接地改变实参的值
4)引申: 函数调用时,用n指针(形参)改变n-1指针(实参)的值。
//函数调用时,形参传给实参,用实参取地址,传给形参,在被调用函数里面用*p,来改变实参,把运算结果传出来。
//指针作为函数参数的精髓。
int getMem3(char **myp1, int *mylen1, char **myp2, int *mylen2)
{
int ret = 0;
char *tmp1, *tmp2;
tmp1 = (char *)malloc(100);
strcpy(tmp1, "1132233");
//间接赋值
*mylen1 = strlen(tmp1); //1级指针
*myp1 = tmp1; //2级指针的间接赋值
tmp2 = (char *)malloc(200);
strcpy(tmp2, "aaaaavbdddddddd");
*mylen2 = strlen(tmp2); //1级指针
*myp2 = tmp2; //2级指针的间接赋值
return ret;
}
int main35()
{
int ret = 0;
char *p1 = NULL;
int len1 = 0;
char *p2 = NULL;
int len2 = 0;
ret = getMem3(&p1, &len1, &p2, &len2);
if (ret != 0)
{
printf("func getMem3() err:%d \n", ret);
return ret;
}
printf("p1:%s \n", p1);
printf("p2:%s \n", p2);
if (p1 != NULL)
{
free(p1);
p1 = NULL;
}
if (p2 != NULL)
{
free(p2);
p2 = NULL;
}
printf("p1:%d \n", p1);
system("pause");
return ret;
}
铁律3:理解指针必须和内存四区概念相结合
主调函数 被调函数
主调函数可把堆区、栈区、全局数据内存地址传给被调用函数
被调用函数只能返回堆区、全局数据
内存分配方式
指针做函数参数,是有输入和输出特性的。
铁律4:应用指针必须和函数调用相结合(指针做函数参数)
铁律5:一级指针典型用法(指针做函数参数)
一级指针做输入
int showbuf(char *p)
int showArray(int *array,int iNum)
一级指针做输出
int geLen(char *pFileName,int *pfileLen);
理解
主调函数还是被调用函数分配内存
被调用函数是在heap/stack上分配内存
铁律6:二级指针典型用法(指针做函数参数)
二级指针做输入
int main(int arc ,char *arg[]); 字符串数组
int showMatrix(int [3][4], int iLine);
二级指针做输出
int Demo64_GetTeacher(Teacher **ppTeacher);
int Demo65_GetTeacher_Free(Teacher **ppTeacher);
int getData(char **data, int *dataLen);
Int getData_Free(void *data);
Int getData_Free2(void **data); //避免野指针
理解
主调函数还是被调用函数分配内存
被调用函数是在heap/stack上分配内存
铁律7:三级指针输出典型用法
三级指针做输出
int getFileAllLine(char ***content, int *pLine);
int getFileAllLine_Free(char ***content, int *pLine);
理解
主调函数还是被调用函数分配内存
被调用函数是在heap/stack上分配内存
铁律8:杂项,指针用法几点扩充
1)野指针 2种free形式
int getData(char **data, int *dataLen);
int getData_Free(void *data);
int getData_Free2(void **data);
2)2次调用
主调函数第一次调用被调用函数求长度;根据长度,分配内存,调用被调用函数。
3)返回值char /int/char *
4)C程序书写结构
商业软件,每一个出错的地方都要有日志,日志级别
铁律9:一般应用禁用malloc/new