[英]How does the scanf function work in C?
為什么在scanf
函數中需要&符號(&)。 以下C代碼中的輸出或錯誤類型(編譯或運行時)是什么?
#include <stdio.h>
void main() {
int a;
printf("enter integer:");
scanf("%d", a);
}
&
in C是一個返回操作數地址的運算符。 可以這樣想,如果你只是給scanf
變量a
而沒有&
,它將被傳遞給它的值,這意味着scanf
將無法設置它的值供你看。 通過引用傳遞它(使用&
實際將指針傳遞給a
)允許scanf
設置它,以便調用函數也可以看到更改。
關於具體的錯誤,你無法真正說出來。 行為未定義。 有時,它可能會默默地繼續運行,而您不知道scanf
在程序中的某處更改了某些值。 有時它會導致程序立即崩潰,就像在這種情況下:
#include <stdio.h>
int main()
{
int a;
printf("enter integer: ");
scanf("%d",a);
printf("entered integer: %d\n", a);
return 0;
}
編譯它顯示了這個:
$ gcc -o test test.c
test.c: In function ‘main’:
test.c:6: warning: format ‘%d’ expects type ‘int *’, but argument 2 has type ‘int’
並執行顯示分段錯誤:
$ ./test
enter integer: 2
Segmentation fault
在C中,所有函數參數都按值傳遞; 對函數形式參數的任何更改都不會反映在實際參數中。 例如:
void foo(int bar)
{
bar = bar + 1;
}
int main(void)
{
int x = 0;
printf("x before foo = %d\n", x);
foo(x);
printf("x after foo = %d\n", x);
return 0;
}
該計划的輸出將是
x before foo = 0 x after foo = 0
因為bar
接收x
(0)的值,而不是x
本身的引用。 更改bar
對x
沒有影響。
在C中,解決這個問題的方法是將指針傳遞給變量:
void foo(int *bar)
{
*bar = *bar + 1;
}
int main(void)
{
int x = 0;
printf("x before foo = %d\n", x);
foo(&x);
printf("x after foo = %d\n", x);
return 0;
}
現在程序的輸出是
x before foo = 0 x after foo = 1
這一次,形式參數bar
不是int,而是指向 int的指針 ,它接收x
的地址 (由foo
調用中的表達式&x
給出),而不是x中包含的值。 表達式*bar
表示“獲取位置欄中的值指向 ”,因此*bar = *bar + 1
對應於x = x + 1
。
由於scanf()
需要寫入其參數,因此它希望將這些參數鍵入為指針。 “%d”轉換說明符期望相應的參數是指向int( int *
)的指針,“%u”轉換說明符期望指向unsigned int( unsigned *
),“%s”需要指向char的指針( char *
),“%f”需要指向float( float *
)等的指針。在您的示例中,由於a
是類型int
,因此需要使用表達式&a
來獲取指針。
請注意,如果a
已經是指針類型,則不需要在對scanf()
的調用中使用&
運算符:
int main(void)
{
int a, *pa; // declare pa as a pointer to int
...
pa = &a; // assign address of a to pa
scanf("%d", pa); // scanf() will write to a through pa
...
}
另請注意,將數組傳遞給函數時(例如使用“%s”轉換說明符讀取字符串時),您不需要使用&
運算符; 數組表達式將隱式轉換為指針類型:
int main(void)
{
char name[20];
...
scanf("%19s", name); // name implicitly converted from "char [20]" to "char *"
...
}
如果你問這樣的問題,我建議你現在就學習“它就是這樣”。
您將了解到您需要一個&符號,因為scanf
需要一個或多個指針參數。 如果a是int變量,則它不是指針。 &a(“a的地址”)是一個指針,因此它將與scanf
。
這是因為在C中,函數參數是按值傳遞的 。 為了使scanf()
函數來修改“ a
在你的main()函數”變“的地址, a
”應當給予scanf()
符號的,因此使用(地址)。
因為scanf
需要一個指向該值將進入的變量(即引用)的指針。
您並不總是需要使用&
with scanf
。 你需要做的是傳遞指針 。 如果你是C新手,你應該花點時間閱讀comp.lang.c FAQ:
特別:
scanf
的'&'只需要獲取變量的地址。 您可以通過使用指針使用scanf
而不使用'&':
int myInt;
int * pointer_to_int;
pointer_to_int = &myInt;
scanf("%d", pointer_to_int);
通常,使用'&'通常比創建指針更容易,以避免使用'&'。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.