簡體   English   中英

在scanf中沒有`&`的情況下,%s如何在c中工作?

[英]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()返回成功分配的次數,並且應該在健壯的代碼中檢查此值。 此外,請注意,將%sscanf()一起使用時,應始終指定最大寬度,以避免緩沖區溢出。 在這里,使用%99s ,在數組末尾留出空終止符( \\0 )。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM