按地址传递、scanf、取消引用
Pass by address, scanf, de-referencing
我编写了一个采用以下概念的程序:
我创建一个整数 x
通过地址传递给一个函数,连同一个文件名,该函数打开文件(如果可用),扫描第一行并将 pX
指向的值设置为等于到扫描线。
只是它不起作用,而且我看不出我做错了什么。据我所知,下面的代码通常是如何完成它的,但我不确定我是否没有正确使用 scanf()
指针或什么。
void foo() {
char input[20] = "test.txt";
int x = 1;
bar(input, &x);
}
void bar(char *fileName, int *pX) {
FILE *fp = fopen(fileName, "r");
char *buffer = malloc(15 * sizeof(int));
fgets(buffer, 15, fp);
scanf(buffer, "%d", *pX);
free(buffer);
fclose(fp);
}
换行:
scanf(buffer, "%d", *pX);
至:
sscanf(buffer, "%d", pX);
您需要函数 sscanf 来完成您想要做的事情。
scanf
和sscanf
都以指针作为参数。 pX
属于 int *
类型,因此指向 int
的指针应该适合您。您传递的 *pX
是此指针的 内容 ,换句话说,int
.
此外,更改行:
char *buffer = malloc(15 * sizeof(int));
至:
char *buffer = malloc(15 * sizeof(char));
或者简单地说:
char *buffer = malloc(15);
并且总是 check the result of malloc :
if (buffer == NULL){
...
}
首先,C语言中没有引用传递,函数参数都是按值传递的。通过传递一个指向数据的指针,我们模拟实现了与pass-by-reference相同的效果,但这并不意味着C有任何pass-by-reference的概念。
也就是说,问题好像是
scanf(buffer, "%d", *pX);
^^^^
其中
当前语法无效并调用 undefined behavior. Probably you need sscanf()
.
px
已经是指向 int
的指针。通过 px
将是正确且足够的。
故事的寓意:启用编译器警告并注意它们。他们在那里是有原因的。启用适当的警告后,您应该会看到类似
的内容
warning: format %d
expects argument of type int *
, but argument 3 has type int
[-Wformat=
]
最后,
- 在使用文件指针之前,始终检查
fopen()
的 return 值是否成功。
- 检查
scanf()
的 return 值以确保扫描成功。
- 检查
fgets()
的 return 值以确保成功
...基本上,检查所有库调用的 return 值以确保它们按预期工作 。
你错误地使用了scanf()
:要么直接使用scanf
解析标准输入,要么使用sscanf()
解析fgets()
读取的字符串。再者,pX
已经是指向int
的指针了,也就是sscanf()
期望存放它转换的int
值,直接传过去:sscanf(buffer, "%d", pX);
这是修改后的版本:
int bar(const char *fileName, int *pX) {
char buffer[15];
FILE *fp = fopen(fileName, "r");
int success = 0;
if (fp != NULL) {
fgets(buffer, sizeof buffer, fp);
if (sscanf(buffer, "%d", pX) == 1)
success = 1;
fclose(fp);
}
return success;
}
void foo(void) {
int x = 1;
bar("test.txt", &x);
/* do something with x */
}
备注:
- 不需要分配
buf
,只需要将其设为自动存储的本地数组即可。
char *buffer = malloc(15 * sizeof(int));
是不正确的:您分配 space 给 15 int
而不是 15 个字符,根据定义其大小为 1。使用目标类型的大小来避免任何不一致:
char *buffer = malloc(15 * sizeof(*buffer));
始终检查 malloc()
的 return 值以避免潜在的未定义行为。
- 从
fp
读取而不检查 fopen
是否成功有潜在的未定义行为。
- 不修改
filename
指向的数组内容,使之成为const char *
.
- 它可能对
bar
到 return 一个成功指标有用。
- 在编译时启用更多警告:
gcc -Wall -Wextra -Werror
或 clang -Weverything -Werror
可能发现了 scanf
中的错误。
我编写了一个采用以下概念的程序:
我创建一个整数 x
通过地址传递给一个函数,连同一个文件名,该函数打开文件(如果可用),扫描第一行并将 pX
指向的值设置为等于到扫描线。
只是它不起作用,而且我看不出我做错了什么。据我所知,下面的代码通常是如何完成它的,但我不确定我是否没有正确使用 scanf()
指针或什么。
void foo() {
char input[20] = "test.txt";
int x = 1;
bar(input, &x);
}
void bar(char *fileName, int *pX) {
FILE *fp = fopen(fileName, "r");
char *buffer = malloc(15 * sizeof(int));
fgets(buffer, 15, fp);
scanf(buffer, "%d", *pX);
free(buffer);
fclose(fp);
}
换行:
scanf(buffer, "%d", *pX);
至:
sscanf(buffer, "%d", pX);
您需要函数 sscanf 来完成您想要做的事情。
scanf
和sscanf
都以指针作为参数。 pX
属于 int *
类型,因此指向 int
的指针应该适合您。您传递的 *pX
是此指针的 内容 ,换句话说,int
.
此外,更改行:
char *buffer = malloc(15 * sizeof(int));
至:
char *buffer = malloc(15 * sizeof(char));
或者简单地说:
char *buffer = malloc(15);
并且总是 check the result of malloc :
if (buffer == NULL){
...
}
首先,C语言中没有引用传递,函数参数都是按值传递的。通过传递一个指向数据的指针,我们模拟实现了与pass-by-reference相同的效果,但这并不意味着C有任何pass-by-reference的概念。
也就是说,问题好像是
scanf(buffer, "%d", *pX);
^^^^
其中
当前语法无效并调用 undefined behavior. Probably you need
sscanf()
.px
已经是指向int
的指针。通过px
将是正确且足够的。
故事的寓意:启用编译器警告并注意它们。他们在那里是有原因的。启用适当的警告后,您应该会看到类似
的内容warning: format
%d
expects argument of typeint *
, but argument 3 has typeint
[-Wformat=
]
最后,
- 在使用文件指针之前,始终检查
fopen()
的 return 值是否成功。 - 检查
scanf()
的 return 值以确保扫描成功。 - 检查
fgets()
的 return 值以确保成功
...基本上,检查所有库调用的 return 值以确保它们按预期工作 。
你错误地使用了scanf()
:要么直接使用scanf
解析标准输入,要么使用sscanf()
解析fgets()
读取的字符串。再者,pX
已经是指向int
的指针了,也就是sscanf()
期望存放它转换的int
值,直接传过去:sscanf(buffer, "%d", pX);
这是修改后的版本:
int bar(const char *fileName, int *pX) {
char buffer[15];
FILE *fp = fopen(fileName, "r");
int success = 0;
if (fp != NULL) {
fgets(buffer, sizeof buffer, fp);
if (sscanf(buffer, "%d", pX) == 1)
success = 1;
fclose(fp);
}
return success;
}
void foo(void) {
int x = 1;
bar("test.txt", &x);
/* do something with x */
}
备注:
- 不需要分配
buf
,只需要将其设为自动存储的本地数组即可。 char *buffer = malloc(15 * sizeof(int));
是不正确的:您分配 space 给 15int
而不是 15 个字符,根据定义其大小为 1。使用目标类型的大小来避免任何不一致:char *buffer = malloc(15 * sizeof(*buffer));
始终检查
malloc()
的 return 值以避免潜在的未定义行为。- 从
fp
读取而不检查fopen
是否成功有潜在的未定义行为。 - 不修改
filename
指向的数组内容,使之成为const char *
. - 它可能对
bar
到 return 一个成功指标有用。 - 在编译时启用更多警告:
gcc -Wall -Wextra -Werror
或clang -Weverything -Werror
可能发现了scanf
中的错误。