Moh*_*pta 3 c pointers double-pointer
int main(int argc, char **argv)
{
int fd;
int i;
char *line;
if (!(fd = open(argv[1], O_RDWR | O_CREAT)))
{
printf("Error in open\n");
return (0);
}
while ((i = get_next_line(fd, &line)) > 0)
{
printf("%i-%s\n",i, line);
free(line);
}
printf("%i-%s",i, line);
free(line);
}
Run Code Online (Sandbox Code Playgroud)
int main(int argc, char **argv)
{
int fd;
int i;
char **line;
if (!(fd = open(argv[1], O_RDWR | O_CREAT)))
{
printf("Error in open\n");
return (0);
}
while ((i = get_next_line(fd, line)) > 0)
{
printf("%i-%s\n",i, *line);
free(*line);
}
printf("%i-%s",i, *line);
free(*line);
}
Run Code Online (Sandbox Code Playgroud)
第1部分和第2部分之间是否有区别,它们之间的区别是一种用途,**line而另一种用途只是*line。据我了解,两者应该是相同的。
我正在使用它们来测试自己的函数实现,该函数读取并返回1行。
问题:
第1部分的测试工作正常。第2部分测试结果出现分段错误
两者的实现get_next_line()保持相同。
在第一种情况下,使用&line将有效地址传递给get_next_line。但是在第二种情况下,using line将未初始化的变量传递给函数。您没有显示,get_next_line但我认为它*line = blah会执行以下操作:如果传入的line值不是有效地址,则该段当然会段错误(从技术上讲,取消引用未初始化的指针是未定义的行为,因此可能段错误但也可能显示其他任何错误)行为)。
另一种查看方式:
char **line;
get_next_line(fd, line);
printf("%i-%s\n",i, *line);
Run Code Online (Sandbox Code Playgroud)
从本质上讲,这就是第二种情况。我们知道在C语言中,函数参数是通过值传递的。因此,没有任何方法get_next_line可以更改调用方line变量的值。因此,当函数返回值时,line由于从未初始化过,因此其值是不确定的。因此,即使get_next_line不取消引用,line在取消引用printf时仍会导致未定义的行为,line但此时的值显然是未定义的。
将其与第一种等效操作进行比较的情况:
char *line;
get_next_line(fd, &line);
printf("%i-%s\n",i, *line);
Run Code Online (Sandbox Code Playgroud)
在这种情况下,get_next_line可以通过以下方式有效地更改调用方的line变量:
*line = malloc(MY_MAX_LINE_LENGTH);
Run Code Online (Sandbox Code Playgroud)
因此,当函数退出时,调用方的line变量现在具有有效的内存地址,因此可以安全地取消引用。