[英]Why in C does taking input using int format to a char change the value of another char variable?
我使用 scanf() 將“%d”格式的輸入輸入到一個字符中,因為我不想要超過 8 位。 但是這樣做會改變另一個 char 變量的值。
代碼:
#include <stdio.h>
int main() {
char a;
char b;
printf("Enter a: ");
scanf("%c", &a);
printf("a = %c\n", a);
printf("Enter b: ");
scanf("%d", &b);
printf("\na = %d\n", a);
printf("b = %d\n", b);
}
Output:
Enter a: c
a = c
Enter b: 56
a = 0
b = 56
scanf 從標准輸入讀取數據並根據參數格式將它們存儲到附加的 arguments 指向的位置。
scanf("%d", &b);
使用 %d,您將 integer 存儲到無法保存 integer 的 char 變量中。 變量現在增長到它上面的堆棧中的另一個變量。
如果您使用標志“-fstack-protector-all”進行編譯,您應該會在執行時得到 *** 檢測到堆棧粉碎 *** 錯誤。
重復使用scanf()
function 時會出現此問題。 由於scanf()
不會自動跳過 stream 中的空格,因此必須在 %c 轉換說明符前面留一個空格。
我在ISO C11 (-std=c11)
模式下使用 GCC 編譯器來調查這個問題。
#include <stdio.h>
#include <stdlib.h>
/**
* @brief Main Program
* @return Returns 0 if the program is successful.
*/
int main( void )
{
char a;
char b;
printf( "Enter the value of a: " );
scanf( "%c", &a );
printf( "Enter the value of b: " );
scanf( " %c", &b );
/// A space has been added in front of the %c conversion identifier of the scanf() function.
printf( "The value of variable a: %d\n", a );
printf( "The value of variable b: %d\n", b );
return EXIT_SUCCESS;
}
Screenshot 1:
測試應用程序
@JBahn77 謝謝。 我剛剛注意到第二個scanf()
function 使用%d
轉換令牌。 我同意你指出的副作用。 當編譯器一個接一個地加載 memory 中的變量時,就會發生這種情況。 例如,當在變量 b 中輸入足夠大的數字時,我檢查了變量 a 的變化。 我將代碼更改如下。
#include <stdio.h>
#include <stdlib.h>
/**
* @brief Main Program
* @return Returns 0 if the program is successful.
*/
int main( void )
{
char a;
char b;
printf( "Address of variable a: %p\n", &a );
printf( "Address of variable b: %p\n", &b );
printf( "Enter the value of a: " );
scanf( "%c", &a );
printf( "Enter the value of b: " );
scanf( " %d", &b );
printf( "The value of variable a: %d\n", a );
printf( "The value of variable b: %d\n", b );
return EXIT_SUCCESS;
}
然后,當我測試代碼時,我意識到了這種副作用的后果。
Screenshot 1
:測試編輯后的代碼
測試代碼如下圖所示。
Screenshot 2
:結果解讀
scanf
格式字符串中的格式化指令不僅指示如何匹配輸入,還指示要存儲結果值的相應變量的類型。 如果你傳遞一個指向 object 的指針,它的類型與相應指令所期望的不同,那么你將獲得未定義的行為。
即使對於簡單的符號不匹配也是如此,但在您的情況下,您的大小不匹配。 對於沒有大小修飾符的%d
指令, scanf
期望將掃描的 integer 值寫入 [ signed
] int
類型的 object 中。 如果您傳遞的指針改為指向char
,並且在大多數實現中,如果int
大於char
,那么產生的未定義行為特別有可能以不需要的方式表現出來,例如通過在其他變量的值。
如果要將數字掃描為char
大小的 integer,那么您應該
signed char
或unsigned char
,而不是默認char
,並且例如,
unsigned char b;
scanf("%hhu", &b);
%u
是無符號 integer 的格式指令,並且hh
修飾符指示scanf
目標變量是char
/ signed char
/ unsigned char
的大小。
如果你想要一個簽名的 integer 那么它會是相似的,但是使用%d
格式化指令:
signed char b;
scanf("%hhd", &b);
作為一種風格,不要將默認char
用於數字數據,即使您確信需要支持的值范圍是有signed char
和unsigned char
范圍交集的子集。 特別是如果您打算將它與格式化的 I/O 函數一起使用,因為%hhd
或%hhu
是否是默認char
的正確指令是特定於實現的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.