我将scanf函数分组并将此函数命名为eno,并在我的C代码中调用此函数后,它无法正常工作。如果我在代码中单独使用scanf函数,它可以工作。所以我的问题是为什么功能不起作用?这里我显示a = 0和b = 1。总是。 :
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int eno(int, int);
int main() {
int a, b;
eno(a, b);
printf("%d %d", a, b);
}
int eno(int j, int k) {
scanf("%d", &j);
scanf("%d", &k);
}
j
和k
在记忆中不同于a
和b
,所以写j
和k
对a
和b
没有影响。
要让eno
修改a
和b
,你需要将指针传递给a
和b
,如下所示:
eno( &a, &b );
...
void eno( int *j, int *k ) // use void instead of int here; eno doesn't return a value
{
scanf( "%d", j ); // no & operator on j or k, they're already pointers
scanf( "%d", k );
}
这是C的一个非常重要的基本方面。
C按值传递所有函数参数
这意味着最好用一个简单的例子来描述:
void foo(int x)
{
x = 42; // Changes x inside foo but NOT x inside bar
printf("%d\n", x); // Prints 42
}
void bar()
{
int x = 5;
foo(x);
printf("%d\n", x); // Prints 5
}
输出:
42
5
这里要理解的重要一点是x
内部的bar
是x
内部的另一个变量foo
。在x
内对foo
所做的任何改变都不会改变x
中的bar
。
调用foo(x)
将x的值传递给foo
。所以在这种情况下它与foo(5)
相同。
要从x
内部更改bar
中foo
的值,您需要将指针传递给x
。
那是:
void foo(int *x) // Notice the * - Means that foo receives a pointer to int
{
*x = 42; // Notice the * - Change the value of x in bar
printf("%d\n", *x); // Notice the * - Read the value of x in bar
}
void bar()
{
int x = 5;
foo(&x); // Notice the & - it takes the address of x so &x is a pointer to x
printf("%d\n", x);
}
输出:
42
42
因此,要使代码工作,您需要更改eno
,以便它接收指向int而不是int的指针。喜欢:
int eno(int*, int*);
被称为:
eno(&a, &b);
eno(a, b);
^ ^
int eno(int j, int k)
^ ^
值a
和b
分别复制到j
和k
。
当函数eno
返回时,值未被修改。
这是指针进入图片的地方。
eno(&a, &b); // pass the address of a and b
^ ^
int eno(int* j, int* k) // j and k now point to a and b respectively.
^ ^
因为你将a
和b
的值传递给eno
。您需要通过引用传递它们,如下面的代码所示。您需要使用指针通过引用传递。
#include <stdio.h>
int eno(int *,int*);
int main(){
int a,b;
eno(&a,&b);
printf("%d %d",a,b);
}
int eno(int *j,int *k)
{
scanf("%d",j);
scanf("%d",k);
}
编译时,始终启用警告,然后修复这些警告。
对于gcc
,至少使用:-Wall -Wextra -Wconversion -pedantic -std=gnu17
注意:其他编译器使用不同的选项来完成相同的结果。
编译发布的代码导致:
gcc -ggdb -Wall -Wextra -Wconversion -pedantic -std=gnu11 -c "untitled.c"
untitled.c: In function ‘eno’:
untitled.c:17:4: warning: control reaches end of non-void function [-Wreturn-type]
}
^
untitled.c: In function ‘main’:
untitled.c:10:9: warning: ‘a’ is used uninitialized in this function [-Wuninitialized]
eno(a, b);
^~~~~~~~~
untitled.c:10:9: warning: ‘b’ is used uninitialized in this function [-Wuninitialized]
请注意编译器会告诉您有关已发布代码的三个问题。
这是一个可以按需运行的代码版本。
注意正确使用传递变量的地址,以及函数的正确声明:eno()
请注意正确检查scanf()
的调用,以确保操作成功。
包含未使用这些内容的头文件是一种非常糟糕的编程习惯。 I.E. math.h
和string.h
变量(和参数)名称应指示content
或usage
(或更好,两者)
通常,函数名称应该是“活动的”,而不是“神秘的”。它们应该向代码的读者指出函数的作用。
现在,提出的代码只能解决编译器问题,而不是使代码变得更优秀的更微妙的东西:
#include <stdio.h>
//#include <string.h>
//#include <math.h>
#include <stdlib.h> // exit(), EXIT_FAILURE
void eno( int *, int * );
int main( void )
{
int a, b;
eno( &a, &b);
printf("%d %d", a, b);
}
void eno(int *j, int *k)
{
if( scanf("%d", j) != 1 )
{
fprintf( stderr, "scanf to read the variable j failed" );
exit( EXIT_FAILURE );
}
if( scanf("%d", k) != 1 )
{
fprintf( stderr, "scanf to read the variable k failed" );
exit( EXIT_FAILURE );
}
}