我将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);
}
答案 0 :(得分:6)
j
和k
是内存中与a
和b
不同的对象,因此写入j
和k
对a
和b
。
要让eno
修改a
和b
,您需要将 pointers 传递给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 );
}
答案 1 :(得分:6)
这是有关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
的{{1}}的值,您需要将指针传递给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);
答案 2 :(得分:2)
$ git remote set-url origin git@github.com:github/hub.git
origin git@github.com:github/hub.git (fetch)
origin git@github.com:github/hub.git (push)
值eno(a, b);
^ ^
int eno(int j, int k)
^ ^
和a
分别复制到b
和j
中。
当函数k
返回时,未的值已被修改。
这是指针进入图片的地方。
eno
答案 3 :(得分:1)
因为您要将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);
}
答案 4 :(得分:0)
编译时,始终启用警告,然后修复这些警告。
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()
的调用,以确保操作成功。
包括不使用那些内容的头文件是非常糟糕的编程习惯。即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 );
}
}