Difference in calls on main

Asked

Viewed 89 times

0

Guys, I want to know the difference between these two calls?

inserir_inicio(&p, cria_no(0));

p = inserir_fim(p, cria_no(0));

When I try to switch to the style of the first call the code compiles but at the time of execution for everything.

//fim
tipo_lista* inserir_fim (tipo_lista * p, tipo_lista * novo_no)
{
//Se a lista estiver vazia
if(p==NULL)
    return novo_no;

tipo_lista* r = p; //Para manter a referencia ao primeiro elemento
while (p->prox != NULL)
{
    p = p->prox;
}
p->prox = novo_no;
return r;
}

//inicio
tipo_lista * inserir_inicio (tipo_lista * p, tipo_lista * novo_no)
{
novo_no -> prox = p;
return novo_no;
}

//main
int main(){
tipo_lista *p = NULL;

//inserir_inicio(&p, cria_no(0));
p = inserir_fim(p, cria_no(0));
p = inserir_inicio(p, cria_no(1));

imprime_lista(p);

return 0
}

Thank you

  • For a precise answer, we need the function code inserir_inicio and inserir_fim. Although we are almost sure of the problem, without it it is difficult to give a really good answer.

  • @Wilker already added in the question the functions I did.

  • In accordance with the definition of those tasks, inserir_inicio(&p, cria_no(0)) and p = inserir_fim(p, cria_no(0)) cannot both be certain if they refer to the same variable p. Posta also the main(), please

  • Posted, note that is commented.

2 answers

1


In the first you’re passing the pointer to p, soon when you change the value of p within the function insert start, you change the value of p out of function.

While in the second you are copying the value of a variable to the variable within the function, just when you change the value of p within the function, you do not change the value of p out of function.

Mis details https://www.ime.usp.br/~pf/algoritmos/aulas/Pont.html

  • And because of the mistake you can tell me?

  • Need to put more details, like some error message occurs or is it freezing the process? And only one instruction can not know the problem.

  • Like I said there opens the prompt but the program message has stopped working.

1

If it’s the kind of thing I’m thinking about, the reason is "reference emulation". As you may know, functions in C pass their parameters by value/copy. To emulate the reference pass, you need to pass the pointers to the desired parameters and work with these pointers.

A half-haired example to fix:

void badswap (int a, int b){
   int tmp;

   tmp = a;
   a = b;
   b = tmp;
}

void goodswap (int *ap, int *bp){
   int tmp;

   tmp = *ap;
   *ap = *bp;
   *bp = tmp;
}

To add an element to the end of a chained list, you pass the head of the list as parameter, because that head will not be modified. You will only modify the tail by adding an element at the end of it.

Already in the second, to add an element to the head of the list, effectively you have to modify the head of that list: it was previously in the memory location X, now it will be in the memory location Y. For so, you will have to use the reference emulation.

I think to explain the cause of the mistake, I would have to do a table test, "interpreting mentally" the code itself. My best guess, for now, is that there should be some confusion of variables - imagine as if you wrote something like *tmp = *bp; in the code of goodswap. But again, to point out for sure, I would have to see the full code. These Segmentation fault errors are difficult to explain in a "generic way".

Tip: if possible, read us warnings compiler. They may contain useful insights about these errors. There are also other software, such as cppcheck, the splint or even the debugger gdb.

EDIT:

I got home and tested the modified code in Clang. Well, as I imagined, the error is precisely in the parameter passage.

First of all, the way you did these two functions is different from what I had thought, but it’s even cleaner and more functional. In this sense, much of my comment on reference emulation is unnecessary.

Secondly, to cut to the chase, here’s Clang’s message:

testno.c:66:22: warning: incompatible pointer types passing 'tipo_lista **' (aka 'struct tipo_lista **') to parameter of type
      'tipo_lista *' (aka 'struct tipo_lista *'); remove & [-Wincompatible-pointer-types]
  p = inserir_inicio(&p,cria_no(2));
                     ^~
testno.c:37:43: note: passing argument to parameter 'p' here
tipo_lista * inserir_inicio (tipo_lista * p, tipo_lista * novo_no)
                                          ^
1 warning generated.

With this, the function waits for a pointer, but you are passing a pointer-to-the-pointer. It is not surprising that you will have an erratic behavior - if I am not mistaken, in fact this would be a case of undefined behavior: the compiler is free to do as he pleases. By "well understood", I mean "anything from firing nuclear missiles if there’s hardware for it to melt the monitor".

BUT, assuming the compiler translates this as "obvious" as possible, he simply treats &p as if it were a memory position. "The programmer knows what he is doing". Since this memory position was not legally allocated, it can be anywhere, most likely in a segment that does not belong to the program. And you’ll get a beautiful SIGSEGV.

I hope I’ve helped!

Post Scriptum: I left out some nauseous tests in my example on IDEONE; for example, if the memory was really allocated. Still, you can spend...

  • Yes, I suspect that’s exactly it: p is probably a pointer to the first element of the list, and therefore inserir_inicio() has to change the value to which p points within main(). Already to inserir_fim(), no need to do p point to another object in memory, then just pass the address to which p points out.

  • @Anderson Torres tries to compile, I put the functions in the question. Thank you

  • I did a test code here, and it turns out that everything works as it should. repl it. and another in [IDEONE] (https://ideone.com/n2n3G6). I created a function cria_no without much emotion, I believe it is something close to what you want. What I’m finding strange is that in fact the compiler doesn’t complain about the type of the variable here, when I use the function the wrong way. Since I have no way to pass parameters to the gcc (especially the most important -Wall) at IDEONE, I’ll leave it as it is. Coming home, I test this more carefully.

  • I understand, but that’s not what I wanted. I just found out here. It’s kind of the function, if I do a function: void insere (tipo_lista*p, tipo_lista*novo_no) in mainI have to call insere(&raiz_principal, cria_no(10)); got it?

  • Already if I do a function tipo_lista * insere (tipo_lista *p, tipo_lista*novo_no) in main I must call raiz_principal = insere(raiz_principal, cria_no(0));

  • I think it’s actually more than that, because when you make these reference calls (emulated), you actually treat these parameters as if they were returns (in the sense of return {alguma coisa}).

Show 1 more comment

Browser other questions tagged

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