简体   繁体   中英

C programming Arrays and Pointers

The following code is from a practice test. The question is to determine if it is correct or not and what it would print if it is. It does compile and print but I do not understand why it is printing what it is.

Anyone have any ideas?

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

Not everything that compiles is good C code. What you are doing here is extremely dangerous.

You are declaring an array on the stack in getThreeNumber(); and returning a pointer to it to the callee ( main in this case). int a[3] gets destroyed when getThreeNumber() finishes execution, so the pointer that is passed back to main could contain garbage.

This provokes undefined behaviour .

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

A correct way to do it would be to allocate the memory on the heap:

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

remember though that you have to free the memory in your main:

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

However the exact opposite of what you are trying to do is allowed (and common in C programming). You can send the address of your stack allocated array to a function that alters it. This is done as follows:

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

The reason the second program behaves well, is because the array is never destroyed until it goes out of scope. changeNumbers() 's stack frame goes on "top" of main, which means the memory addresses below it are safe from going out of scope and being destroyed.

In simple words: In the first situation when main is accessing the values in array, its owner function is already done executing and it's stack has resolved.(every variable getThreeNumbers() declared on the stack could be garbage)

In the second situation. when changeNumbers() is accessing the array, the owner of the array ( main ) is not done executing yet! it is still chilling and waiting for changeNumbers() to finish execution before taking control again.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM