【初学随记,若有错误请多多指出】
其实是在学习链表的时候碰到的,由于链表初学,有一点绕
用以下代码做了实验:
#include <stdio.h>
//#include <string.h>
#include <stdlib.h>
void changep(char **h);
int main(){
char *p=NULL;//(char*)malloc(sizeof(char))
// *p='a';
// int p=52;
// printf("in main p=%c\n",*p);
// printf("in main &p=%x\n",p);
changep(&p);
printf("agn in main p=%c\n",*p);
printf("agn in main &p=%x\n",p);
return 0;
}
void changep(char **h){
// printf("in changep p=%c\n",*h);
// printf("in changep &p=%x\n",h);
char *pp=(char*)malloc(1);
printf("in changep &pp=%x\n",pp);
*pp='b';
*h=pp;
printf("in changep &h=%x\n",h);
printf("agn in changep h=%c\n",**h);
}
发现一些问题:
A、当main函数中的p不论是char(字符)(因为当时知道,数组或字符串本身的变量名就是它们的地址,但不确定字符或其他类型的变量是怎么操作的)或者int类型时,若定义p时就定义的 *p,若需要将*p这个指针变量保存的地址传入changep函数,直接changep(p)就好了(也就是还是传的值),这时能做的事情是修改*p所指向的地址代表的值,实际是由另一个副本指针完成的(和p一样指向了同样的地址)。
B、若定义p时,无论何种类型,并没有把p定义为指针,此时changep(p)传入的是p的值、changep(&p)传入的是p的地址,在changep函数内,使用p即可做地址修改
C、若定义p时,char *p=“1234”; 指针p存储的地址是在常量空间里的(别的大佬是这么说的,经过测试确实地址比较小),
char *p=(char*)malloc(10)或char p[]="1234";此时p存储的地址不是常量空间的,但是赋值也只能一个地址一个地址地赋,若用p=“1234”,又会让p存储的地址是常量空间的地址。
所以,在这种情况下如果想把p="1234"改为p="a123";
1、在函数外修改时,若定义p采用char *p=“1234”的形式,需要再定义一个char *a=“a123”,然后让p=a,*p=*a都不行,因为这时候*p的值是存放在常量里的,是const,只能修改p的指向来“看起来像”修改了*p的值。
2、若定义采用的是malloc(需要逐一赋值)或char p[]的形式,此时p的地址指向的值是可以随意修改的,遍历*(p+n)修改即可
3、若在函数内部,“1、”的情况是改不了的,因为传进去的值是常量“1234”的地址,通过这个地址改不了“1234”的值,修改p的指向呢,又只能修改到副本p的指向,函数外的指向并不会变动。此时唯二的解决方案是:①传入&p,“指向这个指针的指针”(指针也是一个变量,存放的值是地址,那么要存放这个变量,也是有一个地址的),传入指针的地址,就可以做到通过修改这个地址上代表的值,来修改p的指向,像“1、”那样做就行了。②传入的还是指针p的值而不是地址,那么修改了p之后,将这个地址返回,让函数外的p接收这个返回的地址,也可以起到同样的作用。PS:学习C时,老师有一个说法是尽量避免返回地址。具体以后再研究吧。
4、若在函数内部,p的定义采用“2、”的方式时,把p[]或p传入函数即可,虽然传入函数的还是指针的值(只能修改指针指向地址代表的值,而不是改变指针的指向),但已经可以满足我们的希望和要求了。