以下代码来自练习测试.问题是确定它是否正确以及如果它是什么会打印.它确实编译和打印,但我不明白它为什么打印它是什么.
有人有主意吗?
#includeint *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; }
ForeverStude.. 6
并非所有编译的都是好的C代码.你在这做什么是非常危险的.
您在堆栈中声明一个数组getThreeNumber();
并将指针返回给被调用者(main
在本例中).完成执行后int a[3]
会被销毁getThreeNumber()
,因此传回的指针main
可能包含垃圾.
这引发了未定义的行为.
#includeint *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编程中很常见).您可以将堆栈分配的数组的地址发送到改变它的函数.这样做如下:
#includevoid 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()
访问数组时,array(main
)的所有者尚未执行!changeNumbers()
在再次控制之前,它仍然令人不寒而栗,等待 完成执行.
并非所有编译的都是好的C代码.你在这做什么是非常危险的.
您在堆栈中声明一个数组getThreeNumber();
并将指针返回给被调用者(main
在本例中).完成执行后int a[3]
会被销毁getThreeNumber()
,因此传回的指针main
可能包含垃圾.
这引发了未定义的行为.
#includeint *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编程中很常见).您可以将堆栈分配的数组的地址发送到改变它的函数.这样做如下:
#includevoid 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()
访问数组时,array(main
)的所有者尚未执行!changeNumbers()
在再次控制之前,它仍然令人不寒而栗,等待 完成执行.