将指针传递给函数时为什么会出现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
副本。
其他差异
- 错误检查:检查
scanf
和malloc
返回值 - 没有内存泄漏:最后是
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
。