簡體   English   中英

為什么即使我在 3 個大小的數組上分配了 4 個值,我的代碼仍在運行?

[英]Why is my code running even though I'm assigning 4 values on a 3 sized array?

順便說一句,我對編碼相當陌生:)

基本上我正在嘗試做一個程序,詢問學生他有多少個成績( div ),並計算總成績(nota=grade, im portuguese)。 請注意,在每次嘗試時,我總是輸入 '3' 和div的值,而且我只顯示了部分代碼

至於 [CORRECT VERSION],在我看來一切正常並且運行良好。

**[CORRECT VERSION]**

    short unsigned int div, i;
    printf("Pretende fazer a media de quantas notas?(Máximo é 10): ");
    scanf("%hd", &div);
    float nota[div], media, soma = 0;
    for(i = 0; i < div; i++) { //duvida linhas 25-26
        pergunta:
        printf("A %dª nota foi: ", i+1);
        scanf("%f", &nota[i]);
       if((nota[i] < 0) || (nota[i] >20)) {
        printf("\n(Erro: Por favor insira valores de 0 a 20\n");
        goto pergunta;

我的疑問與for循環中的 ["NON-SENSE" VERSION] for 我知道我在制作i++ ,循環的第一次運行將假定i0 ,但在for循環中, i將為1 由於array_size=3,三年級(nota)將沒有要分配的槽位(因為nota[0] 將被跳過,這使得它為0 對嗎?只剩下2 個槽位),但循環仍然運行3次,要求 3 個等級並給我總體。

**["NON-SENSE VERSION]**

    short unsigned int div, i;
    printf("Pretende fazer a media de quantas notas?(Máximo é 10): ");
    scanf("%hd", &div);
    float nota[div], media, soma = 0;
    for(i = 0; i++ < div;) { //duvida linhas 25-26
        pergunta:
        printf("A %dª nota foi: ", i);
        scanf("%f", &nota[i]);
       if((nota[i] < 0) || (nota[i] >20)) {
        printf("\n(Erro: Por favor insira valores de 0 a 20\n");
        goto pergunta;

但是,將div替換為3 ,即使它與先前版本中假定的div值相同,我也會遇到分段錯誤(以及其他一些實驗總線錯誤

[VERSION WITHOUT div GIVING A NORMAL ERROR]
    short unsigned int div, i;
    //printf("Pretende fazer a media de quantas notas?(Máximo é 10): ");
    //scanf("%hd", &div);
    float nota[3], media, soma = 0;
    for(i = 0; i++ < 3;) { //duvida linhas 25-26
        pergunta:
        printf("A %dª nota foi: ", i);
        scanf("%f", &nota[i]);
       if((nota[i] < 0) || (nota[i] >20)) {
        printf("\n(Erro: Por favor insira valores de 0 a 20\n");
        goto pergunta;

你能解釋一下我遺漏了什么嗎,為什么即使是 ["NON-SENSE" VERSION] 也能運行,即使它和上一個幾乎一樣?

這里有很多東西要解壓,但讓我們按順序完成。

首先,不要這樣做:

unsigned div;
scanf("%hd", &div);
float nota[div], media, soma = 0;

如果您知道學生可以輸入的最大成績數量或使用動態分配,您應該預定義 MAX_SIZE。 可以在此 StackOverflow 問題中找到有關此的更多信息。 您正在做的是創建一個 VLA - 可變長度數組。 這是在 C99 標准中添加的,但使用它會降低可移植性,因為並非所有編譯器都遵守該標准。

其次,您使用的是非慣用的 for 循環。 編程中的一個習語是做某些事情的事實上的標准。 我們使用習語是因為它減少了出錯的機會,並使其他人更容易閱讀和維護我們的代碼。 這就是為什么我們堅持

for(int i = 0, i < n; i++){}

我想你知道這一點(正如你所說的無意義),但我只是把它放在那里給任何可能嘗試使用看起來像這樣的代碼for(i = 0; i++ < 3;) - 這會給你留下你不想要的嚴重錯誤和行為。

將這兩者結合在一起,我們可以看到這里發生了什么:在您的無意義示例中,您使用的是 VLA。 它的工作方式取決於編譯器,但我猜在這種情況下編譯器會查看變量 div 的類型 - 因為它是一個無符號短整型,它知道該值在 (0 - 65,535 )*,所以值比較小。 因為它是一個很小的值,所以它在堆棧上分配了足夠的內存來容納一個最多約 65k 長的數組。 這意味着您可以“安全地”讀取和寫入該內存而不會出現堆棧溢出,因為操作系統已授予您的程序寫入內存中 65k 元素點的權限。

在另一種情況下,您對編譯器說您的數組將有 3 個元素長,因此您的程序僅從操作系統請求 3 個元素的空間。 然后操作系統不喜歡你試圖從它沒有給你的內存中讀寫,所以你最終會出現錯誤。

最后注意:請不要使用goto

*假設 unsigned short 是 16b long,這是最小值 - 它可以更長,具體取決於系統。

暫無
暫無

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

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