[英]How does %s work in c without `&` in scanf?
我對c中的%s
感到有些困惑。 我是編程新手,我正在學習c作為我的拳頭PL
%s
如何在c中工作。 我發現使用%s
時不需要使用&
在scanf中。 為什么會這樣呢? 為什么我使用時%s
給出細分錯誤
char *a="how are you";
printf("%s",*a);
我已經閱讀了此鏈接:- 在C中正確使用%s-非常基本的水平,但是我想以粗體顯示問題的答案。
您需要了解指針與char
變量之間的區別。
通常在scanf()
傳遞一個數組以匹配%s
說明符,然后在該位置使用指向數組第一個元素的指針。 對於%d
等其他說明符,您需要傳遞目標變量的地址,以允許scanf()
將結果存儲在其中。
相反, printf()
不會在任何地方存儲結果,因此它只需要變量的值即可, "%s"
說明符除外,該說明符需要終止非'\\0'
char
值數組的第一個元素的地址由'\\0'
。
在您的示例中,您傳遞了一個char
變量, printf()
將其作為地址並嘗試對其進行解除引用,這將導致分段錯誤,因為它期望該變量是一個充滿char
並終止的數組的地址帶有' 0'
。
注意 : printf("%s", *a);
等效於printf("%s", a[0]);
因此,您可以清楚地看到傳遞給"%s"
的變量的類型為char
並且printf()
將使用(char *) 'h'
作為有效指針,執行*(char *) 'h'
操作,但大多數情況下可能不會。
聲明“在使用%s時不需要使用&在scanf中”可能會誤導您。 關於讀入和存儲值的scanf
格式說明符始終需要指向相應類型對象的指針。 這通常是由一元&
運算符實現的,該運算符返回對象的地址。 但是某些類型(例如數組)會自動衰減為指向數組第一個元素的指針,因此以下代碼實際上會傳遞一個指針:
char text[100] = "";
scanf("%s", text); // array automatically decays to a pointer to the first element.
scanf("%s", &text[0]); // explicitly take the address of the first element
如果您沒有數組,而是一個指向char的指針,則代碼將更改如下:
char *text2 = malloc(100);
scanf("%s", text2); // text2 is a pointer, not an array
同樣,您不需要&
,因為您已經傳遞了指針值。
因此,聲明“使用%s時不需要在scanf中使用&”是正確的,因為%s
始終需要一個指向字符序列的指針,並且您可以傳遞一個自動衰減到指針的數組,也可以直接傳遞一個指針。
從兩個角度來看,您的代碼是錯誤的:
char *a="how are you";
printf("%s",*a);
首先, *a
不是指針,而是單個字符值(在您的情況下為'h'
),當將其轉換為指針值時,它將類似於內存地址0x0000001A
。 對此進行訪問會產生未定義的行為/ seg錯誤。
其次,它是一個printf
,而不是scanf
。 如果需要printf,請輸入:
char *a="how are you";
printf("%s",a);
如果需要scanf,請輸入:
char a[100];;
scanf("%s",a);
scanf()
函數將指針指向字符數組的第一個元素,並將其作為%s
偽指令的參數。 由於數組標識符會衰減到指向數組第一個元素的指針(在大多數表達式中,包括函數調用),因此僅使用不帶&
地址運算符的數組名稱即可提供正確的指針。 實際上,在此處使用&
運算符是錯誤的。
給定代碼:
char array[100];
int ret_val = scanf("%99s", array);
在這里,標識符array
衰減為指向array[]
的第一個元素的指針,這是scanf()
期望的。 如果相反,這是:
int ret_val = scanf("%99s", &array);
這是不正確的,因為&array
是指向數組array[]
的指針。 區別在於, array
衰減到一個指向一個字節的指針,而&array
是指向100個字節的指針(在這種情況下)。 例如,當涉及指針算術時,這種差異很重要。
在第二個示例中:
char *a = "how are you";
printf("%s", *a);
在這里, a
已經是一個指向數組第一個元素的指針(因為a
是一個指向char
的指針,而"how are you"
是一個字符串文字,在內存中表示為以char
結尾的空終止數組),該數組遞歸為一個指針。表達式中此數組的第一個元素)。 通過使用*a
代替a
,將值'h'
用作printf()
的參數,而不是預期的指針,從而導致未定義的行為。
另外,請注意,在我的第一個示例中, scanf()
的返回值存儲在int
變量ret_val
。 scanf()
返回成功分配的次數,並且應該在健壯的代碼中檢查此值。 此外,請注意,將%s
與scanf()
一起使用時,應始終指定最大寬度,以避免緩沖區溢出。 在這里,使用%99s
,在數組末尾留出空終止符( \\0
)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.