提问人:Kevin Zembower 提问时间:4/6/2022 最后编辑:Vlad from MoscowKevin Zembower 更新时间:4/6/2022 访问量:78
新手:传递指向函数的指针
NEWBIE: passing a pointer to a function
问:
我正在尝试从大约 5 年前涉足 C 中重新学习 C。具体来说,我正在尝试学习如何从 main 中提取许多操作并将它们制作成一个函数,目的是将它们移动到接下来的库文件中。
这似乎正在起作用:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
struct arguments {
char *word_file; /* Default name for input file */
} arguments;
int main (int argc, char *argv[]) {
arguments.word_file = "dummy";
FILE *fp;
fp = fopen(arguments.word_file, "r");
if (fp == NULL) { /* If fopen failed... */
fprintf(stderr, "Error: Unable to open file %s: %s\n",
arguments.word_file, strerror (errno));
exit (8);
}
char word[60];
fgets (word, sizeof(word), fp);
printf("Word is %s\n", word);
}
顺便说一句,“虚拟人”是:
$ cat dummy
dog
cat
$
无论我如何尝试,它要么给我编译错误,要么在我运行它时出现 seg 错误:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
struct arguments {
char *word_file; /* Default name for input file */
} arguments;
void getfile(FILE *fp) {
fp = fopen(arguments.word_file, "r");
if (fp == NULL) { /* If fopen failed... */
fprintf(stderr, "Error: Unable to open file %s: %s\n",
arguments.word_file, strerror (errno));
exit (8);
}
}
int main (int argc, char *argv[]) {
arguments.word_file = "dummy";
FILE *fp;
getfile(fp);
char word[60];
fgets (word, sizeof(word), fp);
printf("Word is %s\n", word);
}
我尝试从 *fp 更改为 fp 再到 &fp,但没有成功。我确信我对文件指针有一些不了解的地方,但无法弄清楚。
感谢您的任何帮助和建议。
-凯文
答:
1赞
Barmar
4/6/2022
#1
fp
不应该是 的参数,它应该是返回值。getfile()
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
struct arguments {
char *word_file; /* Default name for input file */
} arguments;
FILE *getfile() {
FILE *fp = fopen(arguments.word_file, "r");
if (fp == NULL) { /* If fopen failed... */
fprintf(stderr, "Error: Unable to open file %s: %s\n",
arguments.word_file, strerror (errno));
exit (8);
}
return fp;
}
int main (int argc, char *argv[]) {
arguments.word_file = "dummy";
FILE *file_ptr;
file_ptr = getfile();
char word[60];
fgets (word, sizeof(word), file_ptr);
printf("Word is %s\n", word);
}
如果出于某种原因,您确实需要将其作为参数传递,请参阅使用函数更改指针包含的地址
评论
0赞
Kevin Zembower
4/6/2022
感谢您的快速回复。在我看来,这是一种不安全的做法。一旦函数 getfile() 被塞进库文件中,似乎很容易忘记魔术名称是“fp”,有人可能会在主例程中将其重命名为“file_ptr”。
0赞
Barmar
4/6/2022
它不是一个神奇的名字,你可以使用任何你想要的变量。
0赞
Kevin Zembower
4/6/2022
但是我不必在 main 函数和 getfile() 函数中使用“fp”吗?
0赞
Barmar
4/6/2022
不,你为什么会?它只是返回一个值,然后将其分配给调用方中的变量。为什么你认为这与工作方式有什么不同?fp = fopen(...)
0赞
Kevin Zembower
4/6/2022
哇,你是对的,它可以编译并工作。我必须研究这一点才能理解它。再次感谢您的帮助。
1赞
pm100
4/6/2022
#2
您有两个选择
首先,让 'getfile' 返回文件句柄(这是 c 中最惯用的方式)
FILE *getfile() {
FILE *fp = fopen(arguments.word_file, "r");
if (fp == NULL) { /* If fopen failed... */
fprintf(stderr, "Error: Unable to open file %s: %s\n",
arguments.word_file, strerror (errno));
exit (8);
}
return fp;
}
和主要
FILE *fp = getfile(fp);
或者让 getfile 更新基于 fp 值,使用 C 样式的“按引用传递”
void getfile(FILE **fp) {
*fp = fopen(arguments.word_file, "r");
if (*fp == NULL) { /* If fopen failed... */
fprintf(stderr, "Error: Unable to open file %s: %s\n",
arguments.word_file, strerror (errno));
exit (8);
}
}
在主要
File *fp = NULL;
getfile(&fp);
评论
0赞
Kevin Zembower
4/6/2022
非常感谢您的快速回复。我认为你描述的第二种方式是我所想到的。我永远不会得到“**”部分。我得再研究一下。再次感谢。
0赞
pm100
4/6/2022
@KevinZembower将 vlue 作为参数传递给 functin 时,您希望它得到更新 - >您必须传递指向它的指针。在这种情况下,您要传递并已更新的内容本身就是一个指针 -> pass ,具有 arg 类型&fp
FILE**
0赞
Vlad from Moscow
4/6/2022
#3
问题在于指针是通过值传递给函数的。fp
getfile
getfile(fp);
也就是说,该函数处理传递指针值的副本。因此,更改函数中的副本不会反映原始指针的值。fp
您需要通过引用传递指针。
在 C 语言中,通过引用传递意味着通过指向对象的指针间接传递对象。取消引用指针,可以直接访问原始对象。
因此,声明并定义函数,例如
void getfile(FILE **fp) {
*fp = fopen(arguments.word_file, "r");
if ( *fp == NULL) { /* If fopen failed... */
fprintf(stderr, "Error: Unable to open file %s: %s\n",
arguments.word_file, strerror (errno));
exit (8);
}
}
并调用函数
getfile(&fp);
评论
0赞
Kevin Zembower
4/6/2022
非常感谢您的快速回复。我想这就是我所想的。
评论
fp
getfile
fp
main
getfile
-Wall -Wextra -Werror