经过很长一段时间才能使这段代码工作,有人可以向我解释为什么我需要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);
}
答案 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}}副本。
其他差异
w
和scanf
的返回值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`
}
没有任何反应,因为您只需更改p
内MyFunction()
指向的地址。
所以,正如你对整数所做的那样:
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的指针,*w
(wpisuk()
内部*(&w)
1}})是一个指向char的指针,它相当于main()
中的w
,它是main()
中malloc()
的值。因此,您正在做的是将w
返回的值分配给main()
中的指针{{1}}。