[英]C programming language, array, pointer
int main()
{
int j=97;
char arr[4]="Abc";
printf(arr,j);
getch();
return 0;
}
此代碼給我一個堆棧溢出錯誤,為什么? 但是,如果我們使用printf(arr)
而不是printf(arr,j)
printf(arr)
那么它將打印Abc。 請告訴我printf
工作原理,這意味着第一個參數是const char*
類型,因此編譯器如何處理arr。 抱歉! 上面的代碼是正確的,它沒有任何錯誤,我寫錯了。 但是下面的代碼給出了堆棧溢出錯誤。
#include <stdio.h>
int main()
{
int i, a[i];
getch();
return 0;
}
由於變量我采用任何垃圾值,因此將是數組的大小,因此為什么當我使用DEV C ++時,如果我使用TURBO C ++ 3.0,此代碼為何會給出此錯誤,然后顯示error:constant expression required。 如果數組的大小不能可變,那么當我們通過用戶輸入獲取數組的大小時,不會顯示錯誤。 但是為什么在這種情況下。
請告訴我printf的工作原理
首先, 僅將非用戶提供或驗證的字符串傳遞給printf()
的第一個參數!
printf()
在必需的const char*
參數之后接受可變數量的參數(因為printf()
是可變參數函數 )。 第一個const char*
參數是您傳遞格式字符串的位置,以便printf()
知道如何顯示其余參數。
如果arr
字符數組包含用戶輸入的值,則如果字符串恰好包含那些格式占位符,則可能會導致段錯誤,因此格式字符串應始終為硬編碼的常量(或經過驗證的)字符串。 您的代碼示例很簡單,可以看到它確實是一個常數,但是習慣於使用printf("%s", arr)
來顯示字符串而不是將它們直接傳遞給第一個參數(除非您絕對必須這樣做)仍然是一種好習慣。當然)。
就是說,您可以使用格式占位符(以%
開頭的占位符)來格式化輸出。 如果要顯示:
abc 97
然后,您對printf()
調用應為:
printf("%s %d", arr, j);
%s
告訴printf()
第二個參數應解釋為指向以空字符結尾的字符串的指針。 %d
告訴printf()
第三個參數應解釋為帶符號的十進制。
此代碼給我一個堆棧溢出錯誤,為什么?
我看到,現在OP將對行為的描述更改為完全不同的內容,因此我的解釋不再適用於他的代碼。 盡管如此,我關於可變參數功能的觀點仍然存在。
這段代碼導致堆棧無效(或類似的錯誤),因為您未能聲明函數printf
。 printf
是一個所謂的可變參數函數,它接受可變數量的參數。 在C語言中,幾乎總是必須在調用可變參數函數之前先聲明它們。 產生此要求的實際原因是可變參數函數可能(並且經常會)需要一些特殊的方法來傳遞參數。 它通常稱為調用約定 。 如果忘記在調用可變參數函數之前聲明它,則C99之前的編譯器將假定它是普通的非可變函數,並將其作為普通函數調用。 即它將使用錯誤的調用約定,從而導致堆棧無效。 這完全取決於實現方式:有些甚至看起來可以“正常工作”,有些甚至會崩潰。 但是無論如何,您絕對必須在調用可變參數函數之前先聲明它們。
在這種情況下,應在調用printf
之前包括<stdio.h>
。 頭文件<stdio.h>
是一個標准頭,其中包含printf
的聲明。 你忘了做 因此錯誤(最有可能)。 由於它取決於實現,因此無法百分百確定。
否則,您的代碼有效。 該代碼很奇怪,因為您將j
傳遞給printf
而不為其提供格式說明符,但這不是一個錯誤printf
只是忽略了多余的可變參數。 無論如何,您的代碼都應打印Abc
。 在代碼的開頭添加#include <stdio.h>
,假定它已完成您想要的工作,它應該可以正常工作。
同樣,此代碼
#include <stdio.h>
int main()
{
int j=97;
char arr[4]="Abc";
printf(arr,j);
return 0;
}
是一個奇怪的但完全有效的C程序,具有完美定義的輸出(盡管在輸出末尾添加\\n
是個好主意)。
在您的int i, a[i];
行中int i, a[i];
在更正的破損代碼樣本中, a
是i
元素的可變長度數組,但i
未初始化。 因此,您的程序具有未定義的行為。
我懷疑printf()問題是一個紅色的鯡魚,因為以空終止的“ Abc”將忽略其他參數。
你調試過程序了嗎? 如果不能,您是否可以確定故障不在getch()中 ?
我無法復制您的問題,但是為了簡單起見,我注釋掉了getch() 。
順便說一句,為什么不使用fgetc()或getchar()呢? 您打算在更大的程序中使用curses嗎?
=====編輯后添加=====
好吧,不是紅鯡魚,只是OP的一個錯誤。
C ++確實允許分配一個由變量指定的大小的數組。 正如您所推論的那樣,您實際上已經使用隨機(垃圾)大小完成了此操作,並且使堆棧溢出。 使用C ++進行編譯時,通常不再編譯C,並且規則也會更改(取決於特定的編譯器)。
就是說,我不明白您的問題-您需要更加清楚“ 當我們通過用戶輸入獲取數組大小時 ……”
您會看到C語言的字符串被視為char*
並且printf
函數可以直接打印字符串。 要使用此功能打印字符串,應使用以下代碼:
printf("%s", arr);
%s告訴函數第一個變量將為char*
。
如果要同時打印arr和j,則應首先定義格式:
printf("%s%d", arr, j);
%d告訴函數第二個變量將是int
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.