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

时间:2014-12-17 21:07:52

标签: c pointers memory

经过很长一段时间才能使这段代码工作,有人可以向我解释为什么我需要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<stdlib.h>
#include<stdio.h>
#include<string.h>
# 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);
}

5 个答案:

答案 0 :(得分:6)

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

#include <stdio.h>

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的副本。

但是,如果您将按以下方式重写该功能

#include <stdio.h>

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的地址传递给函数,并且在函数内部原始对象本身被更改。

同样适用于帖子中的指针。

如果要定义指针

char *p;
在main中

并将其作为函数

的参数传递
void f( char *p );

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

void f( char **p );

你必须把它称为

f( &p );

答案 1 :(得分:4)

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

如果你有:

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); } 的更改只是本地更改。调用函数看不到变化。

答案 2 :(得分:0)

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

1)基本上,在 main 中,您创建一个指向 nothing 的指针,并调用函数wpisuj()使它指向某事。使用上述想法,您必须发送指针的内存位置,以便函数可以更改指向的位置。如果您仅发送w而不是&w,则会将地址的副本发送到其指向的位置,并且无法更改地址。

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

答案 3 :(得分:0)

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

其他差异

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

scanf

答案 4 :(得分: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`
}

没有任何反应,因为您只需更改pMyFunction()指向的地址。

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

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);

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

  

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

因为您没有放置字符串:如果w(在wpisuj()内)如前所述是指向char的指针,*wwpisuk()内部*(&w) 1}})是一个指向char的指针,它相当于main()中的w,它是main()malloc()的值。因此,您正在做的是将w返回的值分配给main()中的指针{{1}}。