当前位置:  开发笔记 > 编程语言 > 正文

C编程数组和指针

如何解决《C编程数组和指针》经验,为你挑选了1个好方法。

以下代码来自练习测试.问题是确定它是否正确以及如果它是什么会打印.它确实编译和打印,但我不明白它为什么打印它是什么.

有人有主意吗?

#include 
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;
}

ForeverStude.. 6

并非所有编译的都是好的C代码.你在这做什么是非常危险的.

您在堆栈中声明一个数组getThreeNumber();并将指针返回给被调用者(main在本例中).完成执行后int a[3]会被销毁getThreeNumber(),因此传回的指针main可能包含垃圾.

这引发了未定义的行为.

#include 
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 
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()访问数组时,array(main)的所有者尚未执行!changeNumbers()在再次控制之前,它仍然令人不寒而栗,等待 完成执行.



1> ForeverStude..:

并非所有编译的都是好的C代码.你在这做什么是非常危险的.

您在堆栈中声明一个数组getThreeNumber();并将指针返回给被调用者(main在本例中).完成执行后int a[3]会被销毁getThreeNumber(),因此传回的指针main可能包含垃圾.

这引发了未定义的行为.

#include 
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 
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()访问数组时,array(main)的所有者尚未执行!changeNumbers()在再次控制之前,它仍然令人不寒而栗,等待 完成执行.

推荐阅读
Life一切安好
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有