Pointer from a function does not print

Asked

Viewed 48 times

1

So guys, I got a homework assignment here, I started pointers now and I couldn’t quite understand it, I’ve tried in a lot of ways to pass the "i" value to the main function and print it out, but I couldn’t do it at all, currently the code is like this and does not print the line trying to print the pointer. Can someone give me a light on how to do what I want? I thank you in advance!

int conferir(int vetor[], int numero, int *p)
{
    int i=0, flag=0;
    for(i = 0;i < 5; i++){
        if(numero == vetor[i]){
            flag = 1;
            break;
        }
    }
    p = &i;
    return flag;
}

int main()
{
    int v[5], num=0;
    int *p;

    printf("Digite o número para ser conferido com o vetor:\n");
    scanf("%d", &num);

    if(conferir(v,num,p) == 1){
        printf("Esse número existe no vetor");
        printf(" e está na posição %d\n", *p);
        }
    else{
        printf("Esse número não existe no vetor.\n");
        }
}

The vector numbers are being generated randomly in another function, the program runs to the line trying to print the number position in the vector.

Dit:I haven’t posted many questions yet, learning the right way to post, I already apologize for any mistake.

1 answer

3


What happened here: when you switch to the function conferir the variable p, it does just that: the value of p. However, any change that affects the value of p within the function does not interfere in the world outside the function. In compensation, you change a value pointed by p is quite different.

Shall we do a table test? I will "run" the program and track its internal states, as it would run after being compiled by GCC or equivalent. Consider here integers and pointers with 1 bytes for simplicity

First, we start the program. We have the following stack:

00: $$1    # v,v[0]
01: $$2    # v[0]
02: $$3    # v[1]
03: $$4    # v[1]
04: $$5    # v[2]
05: $$6    # v[2]
06: $$7    # v[3]
07: $$8    # v[3]
08: $$9    # v[4]
09: $$A    # v[4]
0A: $$B    # num
0B: $$C    # num
0C: $$D    # p
0D: $$E    # p

All with junk in memory (because they haven’t been initialized). So let’s go to scanf(&num). Let’s assume the person came in with 1:

00: $$1    # *v,v[0]
01: $$2    # v[0]
02: $$3    # v[1]
03: $$4    # v[1]
04: $$5    # v[2]
05: $$6    # v[2]
06: $$7    # v[3]
07: $$8    # v[3]
08: $$9    # v[4]
09: $$A    # v[4]
0A:   1    # num
0B:   0    # num
0C: $$D    # p
0D: $$E    # p

So we call the function conferir. In this case, the compiler understands that we should copy the values of the variables and indicate to the function that they are in their range. We would see globally so the memory:

00: $$1    # v,v[0]
01: $$2    # v[0]
02: $$3    # v[1]
03: $$4    # v[1]
04: $$5    # v[2]
05: $$6    # v[2]
06: $$7    # v[3]
07: $$8    # v[3]
08: $$9    # v[4]
09: $$A    # v[4]
0A:   1    # num
0B:   0    # num
0C: $$D    # p
0D: $$E    # p
0E: $$D    # (conferir) p
0F: $$E    # (conferir) p
10:   1    # (conferir) numero
11:   0    # (conferir) numero
12:  &0G   # (conferir) vetor
13:  &0G   # (conferir) vetor
14:   0    # (conferir) i
15:   0    # (conferir) i
16:   0    # (conferir) flag
17:   0    # (conferir) flag

Note that I am using the notation "&0G" to indicate that it is a pointer to the "memory position" "0" in the "global" scope, not to be confused with whole variables or with the "local positioning" shown below

Locally, we would see something like this:

-6: $$D    # p
-5: $$E    # p
-4:   1    # numero
-3:   0    # numero
-2:  &0G   # vetor
-1:  &0G   # vetor
00:   0    # i
01:   0    # i
02:   0    # flag
03:   0    # flag

In doing p = &i, this is what happens:

-6:  &14G  # p
-5:  &14G  # p
-4:   1    # numero
-3:   0    # numero
-2:  &0G   # vetor
-1:  &0G   # vetor
00:   5    # i
01:   0    # i
02: $$X    # flag
03: $$Y    # flag

In the global vision:

00: $$1    # v,v[0]
01: $$2    # v[0]
02: $$3    # v[1]
03: $$4    # v[1]
04: $$5    # v[2]
05: $$6    # v[2]
06: $$7    # v[3]
07: $$8    # v[3]
08: $$9    # v[4]
09: $$A    # v[4]
0A:   1    # num
0B:   0    # num
0C: $$D    # p
0D: $$E    # p
0E:  &14G  # (conferir) p
0F:  &14G  # (conferir) p
10:   1    # (conferir) numero
11:   0    # (conferir) numero
12:  &0G   # (conferir) vetor
13:  &0G   # (conferir) vetor
14:   5    # (conferir) i
15:   0    # (conferir) i
16: $$X    # (conferir) flag
17: $$Y    # (conferir) flag

Note that the memory value at the positions 0C and 0D were unchanged. When the call returns, we "virtually" lose the function stack, getting just that:

00: $$1    # v,v[0]
01: $$2    # v[0]
02: $$3    # v[1]
03: $$4    # v[1]
04: $$5    # v[2]
05: $$6    # v[2]
06: $$7    # v[3]
07: $$8    # v[3]
08: $$9    # v[4]
09: $$A    # v[4]
0A:   1    # num
0B:   0    # num
0C: $$D    # p
0D: $$E    # p

Which is exactly the previous state. But, how to solve this? The desired behavior would somehow make "global" the value of i without using a return.

To this end, the first thing to pay attention is that we do not wish to change the value of p within of the function, but the value pointed for p. That means what to do p = XXX; is a sin because it would be altering the value of p. To change the value pointed by p, we need to do *p = XXX;. Read more.

The other thing we need to take care of is that we need a memory region adequate to that end. And a junk in the pointer variable will not help us with that. So we have two options:

  • point to a known local variable (should be created at that time)
  • dynamically create a memory space to receive this value

The second approach I won’t even explore here, I just quoted it so you can study further later. In the case of the first, my suggestion is:

  • have any variable integer in main (let’s call it qualquer)
  • no pointer type variables in main
  • move to function conferir the address of the variable qualquer

This would be the modified section:

int conferir(int vetor[], int numero, int *p)
{
    int i=0, flag=0;
    for(i = 0;i < 5; i++){
        if(numero == vetor[i]){
            flag = 1;
            break;
        }
    }
    *p = i;
    return flag;
}

int main()
{
    int v[5], num=0;
    int qualquer;

    printf("Digite o número para ser conferido com o vetor:\n");
    scanf("%d", &num);

    if(conferir(v,num,&qualquer) == 1){
...

Running the table test:

00: $$1    # v,v[0]
01: $$2    # v[0]
02: $$3    # v[1]
03: $$4    # v[1]
04: $$5    # v[2]
05: $$6    # v[2]
06: $$7    # v[3]
07: $$8    # v[3]
08: $$9    # v[4]
09: $$A    # v[4]
0A: $$B    # num
0B: $$C    # num
0C: $$D    # qualquer
0D: $$E    # qualquer

All with junk in memory (because they haven’t been initialized). So let’s go to scanf(&num). Let’s assume the person came in with 1:

00: $$1    # *v,v[0]
01: $$2    # v[0]
02: $$3    # v[1]
03: $$4    # v[1]
04: $$5    # v[2]
05: $$6    # v[2]
06: $$7    # v[3]
07: $$8    # v[3]
08: $$9    # v[4]
09: $$A    # v[4]
0A:   1    # num
0B:   0    # num
0C: $$D    # qualquer
0D: $$E    # qualquer

So we call the function conferir. In this case, the compiler understands that we should copy the values of the variables and indicate to the function that they are in their range. We would see globally so the memory:

00: $$1    # v,v[0]
01: $$2    # v[0]
02: $$3    # v[1]
03: $$4    # v[1]
04: $$5    # v[2]
05: $$6    # v[2]
06: $$7    # v[3]
07: $$8    # v[3]
08: $$9    # v[4]
09: $$A    # v[4]
0A:   1    # num
0B:   0    # num
0C: $$D    # qualquer
0D: $$E    # qualquer
0E:  &CG   # (conferir) p
0F:  &CG   # (conferir) p
10:   1    # (conferir) numero
11:   0    # (conferir) numero
12:  &0G   # (conferir) vetor
13:  &0G   # (conferir) vetor
14:   0    # (conferir) i
15:   0    # (conferir) i
16:   0    # (conferir) flag
17:   0    # (conferir) flag

Note that I am using the notation "&0G" to indicate that it is a pointer to the "memory position" "0" in the "global" scope, not to be confused with whole variables or with the "local positioning" shown below

Locally, we would see something like this:

-6:  &CG   # p
-5:  &CG   # p
-4:   1    # numero
-3:   0    # numero
-2:  &0G   # vetor
-1:  &0G   # vetor
00:   0    # i
01:   0    # i
02:   0    # flag
03:   0    # flag

In doing *p = i, this is what happens:

-6:  &CG   # p
-5:  &CG   # p
-4:   1    # numero
-3:   0    # numero
-2:  &0G   # vetor
-1:  &0G   # vetor
00:   5    # i
01:   0    # i
02: $$X    # flag
03: $$Y    # flag

In the global vision:

00: $$1    # v,v[0]
01: $$2    # v[0]
02: $$3    # v[1]
03: $$4    # v[1]
04: $$5    # v[2]
05: $$6    # v[2]
06: $$7    # v[3]
07: $$8    # v[3]
08: $$9    # v[4]
09: $$A    # v[4]
0A:   1    # num
0B:   0    # num
0C:   5    # qualquer
0D:   0    # qualquer
0E:  &CG   # (conferir) p
0F:  &CG   # (conferir) p
10:   1    # (conferir) numero
11:   0    # (conferir) numero
12:  &0G   # (conferir) vetor
13:  &0G   # (conferir) vetor
14:   0    # (conferir) i
15:   0    # (conferir) i
16: $$X    # (conferir) flag
17: $$Y    # (conferir) flag

When returning from the function and "pop" its variables, we have:

00: $$1    # v,v[0]
01: $$2    # v[0]
02: $$3    # v[1]
03: $$4    # v[1]
04: $$5    # v[2]
05: $$6    # v[2]
06: $$7    # v[3]
07: $$8    # v[3]
08: $$9    # v[4]
09: $$A    # v[4]
0A:   1    # num
0B:   0    # num
0C:   5    # qualquer
0D:   0    # qualquer

With due side effect, which was to change the value of the variable qualquer.

  • Wow, I was hoping for a solution, but not as well-crafted and didactic, thank you very much for the answer and the attention!

  • @placementw, my answer is more didactic than strictly correct. Expecting a technically perfect response from Maniero

Browser other questions tagged

You are not signed in. Login or sign up in order to post.