不是編譯的所有東西都是很好的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()
再次執行控制之前完成執行。
「正確的方式」應該是「* A *正確的方式」..還有其他的選擇可以說是更好的,例如,讓調用者創建一個3個整數的數組並將其作爲參數傳遞。 –
@ M.M最初我暗指最能直接類似的方法來處理他的問題。有趣的是,在你評論之前,我正在給他提供另一個成語 – ForeverStudent