将指针传递给函数时为什么会出现2个星

花了很长时间才使这个代码工作,有人可以向我解释为什么我需要2个星,当我将指针传递给字符串作为函数的参数时? 根据定义,指针将地址保存到将放置特定变量的存储器中。 所以它是一个变量,它有自己的地址,在这个地址下是另一个变量的地址。 好的。 因此,如果我将指针传递给函数,我会使用&符号,因为我必须将指针地址传递给函数。 精细。 但接下来会发生什么。 该函数接收存储器中该指针所在的信息。 好的。 这就是我的理解。 我不明白的是为什么我在定义函数及其参数时需要两颗星。 我传递一个指向char变量的指针。 为什么不取消wpisuj(char * w)。 为什么wpisuj(char ** w)。 内存分配对我来说是不可理解的 – 我使用malloc保留内存,malloc返回此内存的地址,因此我将此地址作为变量w的值。 然后再一些我不明白的东西,如果* w是指针并将新创建的位置的地址保存在内存中,为什么我使用* w来放置一个字符串。 它应该不是*(* w)吗? 由于* w是保留存储器的地址,因此*(* w)是该存储器的内容。

加起来。 我不明白的是:1)为什么wpisuj(char ** w)而不是wpisuj(char * w)2)为什么strcpy( w,bufor)而不是strcpy( (* w),bufor)

#include #include #include # define SIZE 256 void wpisuj(char** pw){ char bufor[256]; scanf("%s", bufor); int l; l=strlen(bufor)+1; *pw=(char*)malloc(l*sizeof(char)); strcpy(*pw, bufor); } int main(){ char* w; wpisuj(&w); printf("%s", w); return 0; } 

如果我也可以询问释放内存。 我是否认为这是明星的核心数量(如下面的代码所示):

 void free_memory(char **w){ free(*w); } 

但是,如果我在main()中释放内存,我会:

 int main(){ w=malloc(sizeof(buffer)+sizeof(char)); /* some code before */ free(w); } 

因为很明显可以考虑以下简单程序

 #include  void f( int x ) { x = x + 20; } int main(void) { int x = 10; printf( "Before the call f( x ) x = %d\n", x ); f( x ); printf( "After the call f( x ) x = %d\n", x ); return 0; } 

输出将是

 Before the call f( x ) x = 10 After the call f( x ) x = 10 

如你所见,x在函数f中没有被处理,因为该函数处理main中定义的对象x的副本。

但是,如果您将以下列方式重写该function

 #include  void f( int *x ) { *x = *x + 20; } int main(void) { int x = 10; printf( "Before the call f( x ) x = %d\n", x ); f( &x ); printf( "After the call f( x ) x = %d\n", x ); return 0; } 

那么在这种情况下输出将是

 Before the call f( x ) x = 10 After the call f( x ) x = 30 

因为我们将原始对象x的地址传递给函数,并且在函数内部原始对象本身被更改。

对于post中的指针,这同样有效。

如果要定义指针

 char *p; 

在main中并将其作为函数的参数传递

 void f( char *p ); 

然后该函数将处理原始对象的副本。 副本的任何更改都不会影响原始指针。 因此,在第一个示例中,您应该传递指向此指针的指针,该指针应该声明为函数

 void f( char **p ); 

你必须称之为

 f( &p ); 

wpisuj传递给char**的原因是当在函数中分配内存并将其分配给*w ,从wpisuj返回时,更改在调用函数中可见。

如果你有:

 void wpisuj(char* w){ char bufor[256]; scanf("%s", bufor); int l; l=strlen(bufor)+1; w=(char*)malloc(l*sizeof(char)); strcpy(w, bufor); } 

w的更改只是本地更改。 调用函数没有看到更改。

好吧,我会解释我对你的问题的理解:每当你想使用一个函数来改变你的变量你需要发送它的地址,否则在你的函数内你将改变一个本地副本(函数的本地副本),一旦它返回,它就会丢失。

1)基本上,在你的main中 ,你创建一个指向什么都没有的指针,你调用函数wpisuj()使它指向某个东西。 使用上述想法,您必须发送指针的内存位置,以便函数可以更改指向的位置。 如果你发送w而不是&w你会发送一份地址副本到它指向的地方,而且无法改变它。

2)你的函数strcpy需要一个特定的输入,它是string的地址,而不是指针的地址。 因此,您使用*w来获取w指向的位置。

下面的代码显示了执行相同操作的不同方法。 主要的区别是wpisuj函数返回指向新分配的字符串的指针(然后main指定给w )。 这种技术避免使用指针到指针,因为wpisuj不需要修改w main's副本。

其他差异

  • 错误检查:检查scanfmalloc返回值
  • 没有内存泄漏:最后是free( w )
  • 更好的安全性: scanf %255s可防止用户溢出缓冲区

 #include  #include  #include  char *wpisuj( void ) { char bufor[256]; if ( scanf( "%255s", bufor ) != 1 ) return( NULL ); char *w = malloc( strlen(bufor) + 1 ); if ( w != NULL ) strcpy( w, bufor ); return( w ); } int main() { char *w; if ( (w = wpisuj()) != NULL ) { printf( "%s\n", w ); free( w ); } return 0; } 

为什么我需要一个双指针呢?

这就是我理解你的问题。 答案是:因为像所有实际参数一样(它们是调用者传递的值的副本 ),传递给函数的指针将把它们的值保存在实际声明它们的范围内(在这种情况下是被调用的函数)范围),不改变调用函数中的任何内容。 这不是你想要的,因为你想改变w的值。

如果你这样做:

 void MyFunction(int* p) { //`p`'s value, like `a`'s value, is NULL *p=(char *)malloc(256*sizeof(char)); //`p`'s value is the starting address of the buffer, but `a` didn't change return; } int main() { char* a; a=NULL; MyFunction(a); return 0; //`a`'s value is still NULL, because MyFunction() changed only its own copy of `a` } 

没有任何事情发生,因为您只需更改MyFunction() p指向的地址。

所以,正如你对整数所做的那样:

 void MyFunction(int* p) { *p=1; return; } int main() { int a; a=0; MyFunction(&a); printf("%d", a); return 0; } 

为指针做同样的事情:

 void MyFunction(int** p) { *p=(char *)malloc(256*sizeof(char)); return; } int main() { char* a; a=NULL; MyFunction(&a); return 0; } 

我不明白的是为什么我在定义函数及其参数时需要两颗星。 我传递一个指向char变量的指针。

为什么不取消wpisuj(char * w)。 为什么wpisuj(char ** w)。

看看你的代码:

wpisuj(&w);

这里的amperstand 取消引用指针w 。 这意味着整个表达式&w具有&w地址值。 所以你传递的是指向char变量的指针的地址 ,该变量是指向char变量的指针 。 哪个是正确的:如果需要更改整数,则传递整数的地址。 如果需要更改指针,则传递指针的地址。 因此使用wpisuj(char** w)甚至是正确的。

然后再一些我不明白的东西,如果* w是指针并将新创建的位置的地址保存在内存中,为什么我使用* w来放置一个字符串。

因为你没有放置一个字符串:如果w (在wpisuj()内部wpisuj()如前所述是指向char的指针, *w (在wpisuk()内部)是一个指向char的指针,它相当于*(&w)main() ,它是main()w的值。 所以你要做的就是将malloc()返回的值赋给main()指针w