2015-12-21 75 views
-1

以下代碼來自練習測試。問題是要確定它是否正確,如果是,它會打印什麼。它編譯和打印,但我不明白爲什麼它正在打印它是什麼。C編程數組和指針

任何人有任何想法?

#include <stdio.h> 
int *getThreeNumbers() 
{ 
    int i; int a[3]; int *p; 
    for (i=0;i<3;i++) 
    { 
     printf("enter an integer\n"); 
     scanf("%d", a+i); 
    } 
    p=a; 
    return p; 
} 

int main() 
{ 
    int *q; int i; 
    q=getThreeNumbers(); 
    printf("the number you entered are:\n"); 
    for (i=0;i<3;i++) 
    printf("%d\n", q[i]); 
    return 0; 
} 

回答

6

不是編譯的所有東西都是很好的C代碼。你在這裏做什麼是非常危險的。

您正在聲明堆棧中的數組getThreeNumber();並將指針返回給被調用者(在這種情況下爲main)。 int a[3]getThreeNumber()完成執行時被破壞,因此返回到main的指針可能包含垃圾。

這挑釁未定義的行爲

#include <stdio.h> 
int *getThreeNumbers() 
{ 
    int i; 
    int a[3]; // a is created on the stack, it is only valid within 
       //the scope of this function 
    int *p; 
    for (i=0;i<3;i++) 
    { 
     printf("enter an integer\n"); 
     scanf("%d", a+i); 
    } 
    p=a; 

    return p; //a will die at this point and there is no guarantee 
       //that other values including garbage is not put in its place, 
       // but you are returning its address anyway. BAD IDEA 
} 

做這將是在堆上分配內存以正確的方式:

int *getThreeNumbers() 
{ 
    int i; 
    int *p = malloc(sizeof(int)*3); 
    for (i=0;i<3;i++) 
    { 
     printf("enter an integer\n"); 
     scanf("%d", &p[i]); 
    } 
    return p; 
} 

但請記住,你需要釋放你的主內存:

int main() 
{ 
    int *q; int i; 
    q=getThreeNumbers(); 
    printf("the number you entered are:\n"); 
    for (i=0;i<3;i++) 
    printf("%d\n", q[i]); 

    free(q); //not necessary in this case, but good form 
    return 0; 
} 

然而,你所要做的恰恰相反(並且在C編程中很常見)。您可以將您的堆棧分配數組的地址發送給修改它的函數。

#include <stdio.h> 
void changeNumbers(int * p) 
{ 
    int i; 
    for (i=0;i<3;i++) 
    { 
     printf("enter an integer\n"); 
     scanf("%d", &p[i]); 
    } 
    printf("\n\n\n"); 
} 

int main() 
{ 
    int q[3]; int i; 
    for (i=0; i<3; ++i) q[i]=0; //initialize to 0 


    printf("the values before changing:\n"); 
    for (i=0;i<3;i++) 
    printf("%d\n", q[i]); 
    printf("\n\n\n", q[i]); 

    changeNumbers(q); 

    printf("the array after modification:\n"); 
    for (i=0;i<3;i++) 
    printf("%d\n", q[i]); 
    return 0; 
} 

第二程序表現良好的原因,是因爲數組是永遠不會被破壞,直到它超出範圍:這是如下完成。 changeNumbers()的堆棧框架位於main的「頂部」,這意味着它下面的內存地址可以遠離範圍並被銷燬。

在簡單的話: 在當main在數組訪問值第一種情況下,它的主人功能已經執行完畢,它的堆棧已經解決了(在棧上聲明的每個變量getThreeNumbers()可能是垃圾)

在第二種情況下。當changeNumbers()正在訪問數組時,數組的所有者(main)尚未執行完畢!它仍然令人不寒而慄,等待changeNumbers()再次執行控制之前完成執行。

+0

「正確的方式」應該是「* A *正確的方式」..還有其他的選擇可以說是更好的,例如,讓調用者創建一個3個整數的數組並將其作爲參數傳遞。 –

+0

@ M.M最初我暗指最能直接類似的方法來處理他的問題。有趣的是,在你評論之前,我正在給他提供另一個成語 – ForeverStudent