如果我们想在另外的一个程序中改变某个指针的值,则必须勇二级指针实现.其实指针作为函数的参数时,只需要遵循一个原则就可以.即:一定要传递你要操作的对象的地址.
void getMemory(char *p, int num)
{
*p = (char *) malloc(num);
}
int main(int argc, char **argv)
{
char *str = NULL;
getMemory(&str, 100);
strcpy(str, "hello!");
puts(str);
exit(0);
}
我用下面这个简单的图示来表示内存:
因为我们想动态申请空间,并把申请的空间的地址赋值给主程序中的指针变量,主程序必须传递该指针的地址(即二级指针).之所以要如此,是由于C语言参数的传递是按值的.即形参是一个临时变量,我们不能通过改变形参的值达到改变实参的值的目的.这其实跟我们在C语言课中强调的传值还是传指针是一个道理.
让我们来分析一下上面的程序.在子程序中,我们想改变的是主程序中指针的值,也就是100(假设是这样)处的内存地址中的值.那么,我们在子程序中就应该操作的是地址100.子程序中我们的指针变量p假设在内存的150处,则150处的值是主程序中的str指针的地址100.也就是p=100. 而*p = ?就是直接改变100处的值.看明白了没有!
也许你会说,如果形参声明为char * p, *p不也是直接操作地址为100处的值吗?这个问题问的非常的好,刚开始我也不是很明白,总觉得是一样的道理.但是当我在调试上面的程序时才使我恍然大悟,原来如此. 哈哈!
从数字上来说,他们的确是一样的,但是他们的类型不一样啊.
char *p; //*p的类型为字符串,当然p的值也是100
*p = (char *) malloc(num);
这种情况编译都不会通过,左右类型不匹配.
char **p; //*p类型仍然是指针
*p = (char *) malloc(num);
左右都是指针类型,这才是正确的
为了在子程序中实现修改指针本身的值,对形参*一次之后必须仍为指针变量.所以需要用二级指针.
几级指针其实不是问题的关键,重点是类型匹配问题.类型将告诉编译器该类型所占据的字节数.
通过上面的例子我们可以看出,只要你能将100处的四个字节(linux下指针的大小为4个字节)的值改为新分配的空间的起始地址,你想用几级指针就用几级指针.