malloc 和 free 错误:int main()
{
char * p =NULL;
p = (char * )malloc(100);
strcpy(p , "hello"); "hello" 实际上是一个地址 将这个地址的内容复制到p 直到 \0 结束
printf("%s" , p);
if( p != NULL)
{
free(p);
// p = NULL; 解决方法
}
//此时 p 是个野指针 , 指向一块垃圾数据
if( p!= NULL)
{
free(p);
}
return 0;
}
释放指针所指的空间, 但是指针的值没有重置为NULL
造成释放通过 if(p != NULL) 判断不出来, 所以 free() 时候要进行 指针重置为 NULL
indirect assignment use pointer
void changevar(int * p )
{
*p = 20;
//通过函数将运算结果甩出来!!!
// **** 很方便的返回多个结果很强大 *****
}
int main()
{
int a = 1;
int * p = &a;
*p = 10;
printf("%d" , a);
// ---------
changevar(&a);
// ---------
printf("%d" , a);
}
通过指针做函数参数的方法 间接赋值改变运算结果形参的提醒:
void changevar(int * p )
{ //参数表中的参数和函数体的参数本质上是一样的
// 参数表的参数多了 个对外属性
*p = 20;
}
字面量的提示:
使用
二级指针修改一级指针的地址:void getMem(char ** p)
{
*p = 200;
//用二级指针间接修改一级指针的指向地址
}
int main()
{
char * p = NULL;
char ** q = NULL;
p =100;
printf("p: %d \n" , p);
q= &p;
getMem(q);
printf("p: %d" , p);
return 0;
//p: 100
//p: 200
}
关键就是内存 和 函数调用的模型图;
为什么用一级指针无法改变以及指针的指向, 堆栈调用图很快就能理解!!!
void getMem2(char * p)
{
p = 400;
//用二级指针间接修改一级指针的指向地址
}
int main()
{
char * p = NULL;
char * q = (char *)malloc(100);
p =100;
printf("p: %d \n" , p);
*q= &p;
getMem2(q);
printf("p: %d" , p);
return 0;
//p: 100
//p: 100
}
指针使用的精髓:不同函数同时操作一块内存空间时,通过内存首地址将内存传过去。运算结果在不同函数中并将其甩出来给主函数。
将计算过程在不同的函数中进行分解。
void getMem(char ** myp1, int * len1 ){ char * tmp1 = (char * )malloc(100); strcpy(tmp1 , "helloworld"); *len1 = strlen(tmp1); *myp1 = tmp1; printf("in func getMem:\n"); printf("tmp1: %s\n" , tmp1); printf("tmp1: %d\n" , tmp1); printf("len1: %d\n" , *len1);}int main(int argc, char * * argv){ char * p1 = NULL; int len1 = 0; getMem(&p1, &len1); printf("in main()\n "); printf("p1: %s\n" , p1); printf("p1: %d\n" , p1); printf("len: %d\n" , len1); return 0;}/* in func getMem:
tmp1: helloworld
tmp1: 136160
len1: 10
in main()
p1: helloworld
p1: 136160
len: 10
*/ 指针做函数参数的典型应用场景:
main 函数 为了完成某个任务 ,写很多子函数。通过指针做函数参数实现 main 和子业务的分层。 模块划分的初步。
分层、 模块、 接口封装和设计、 软件的功能之间的划分 、软件信息系统在一个函数中进行简介赋值:
int main()
{
char from[120];
char to[120];
char * p1 = NULL;
p1 = from;
char * p2 = NULL;
p2 = to;
strcpy(p1, "helloworld");
while( *p1 != '\0')
{
*p2++ = *p1++;
}
*p2 = '\0';//并没有将 '\0'拷进去直接打印会发生错误
printf("to: %s" , to);
return 0;
}
指针间接赋值的推论:使用n级指针 , 更改 n-1 级指针的值。
指针的半壁江山 10 铁律。
另外? 函数参数 回调函数
指针作函数参数的输入和输出特性:
主调函数提前分配内存 将内存传给被调用函数 叫指针的输入
被调函数分配内存将结果输出 供给主调函数使用
学习思路:
没有内存哪有指针, 指针是指向内存地址编号的变量。类型是变量的类型。
指针的关键在内存的分析。内存是如何分配的!!!
铁律4:应用指针必须和函数调用相结合(指针做函数参数)
编号 | 指针函数参数 内存分配方式(级别+堆栈) | 主调函数 实参 | 被调函数 形参 | 备注 |
01 | 1级指针 (做输入) | 堆 | 分配 | 使用 | 一般应用禁用 |
栈 | 分配 | 使用 | 常用 |
Int showbuf(char *p); int showArray(int *array, int iNum) |
02 | 1级指针 (做输出) | 栈 | 使用 | 结果传出 | 常用 |
int geLen(char *pFileName, int *pfileLen); |
03 | 2级指针 (做输入) | 堆 | 分配 | 使用 | 一般应用禁用 |
栈 | 分配 | 使用 | 常用 |
int main(int arc ,char *arg[]); 指针数组 int shouMatrix(int [3][4], int iLine);二维字符串数组 |
04 | 2级指针 (做输出) | 堆 | 使用 | 分配 | 常用,但不建议用,转化成02 |
int getData(char **data, int *dataLen); Int getData_Free(void *data); Int getData_Free(void **data); //避免野指针 |
05 | 3级指针 (做输出) | 堆 | 使用 | 分配 | 不常用 |
int getFileAllLine(char ***content, int *pLine); int getFileAllLine_Free(char ***content, int *pLine); |
指针做函数参数,问题的实质不是指针,而是看内存块,内存块是1维、2维。
1) 如果基础类int变量,不需要用指针;
2) 若内存块是1维、2维。
posted on 2017-07-12 18:18
silvercell 阅读(121)
评论(0) 编辑 收藏 引用 所属分类:
c raise