Problem with Pointers

1

I'm doing a simple exercise where I have to enter two integers and calculate different operations using functions.

The question is that he asks me for these two prototypes of functions:

int * multi (int, int);
int * resta (int, int);

I have several questions:

  • What is the benefit of the function returning a pointer and not a variable of type int with the result?
  • I do not understand very well how the system works to return pointers by means of functions.
  • I leave the code that I did that obviously does not work for me in those two functions.

    #include <stdio.h>
    
    void suma (int, int, int *);
    void divi (int, int, int*);
    int * multi (int, int);
    int * resta (int, int);
    
    
    
    int main()
    {
    int num1,num2,op,results,resultd;
    int *resultm;
    int *resultr;
    
    
    printf("Ingrese el primer numero:  ");
    scanf ("%d",&num1);   
    printf("Ingrese el segundo numero:  ");
    scanf ("%d",&num2); 
    
    printf("Elija una de las siguientes opciones: \n");
    printf (" 1-Suma \n 2-Division \n 3-Multiplicacion \n 4-Resta \n 0-Salir \n");
    scanf("%d",&op);
    
    while (op>0&&op<=4)
     { switch (op)
             { case 1: suma (num1,num2,&results);
                       printf("El resultado es: %d \n", results);
                       break;
               case 2: divi (num1,num2,&resultd);
                       printf("El resultado es: %d \n", resultd);
                       break;
               case 3: resultm= multi(num1,num2);
                       printf("El resultado es: %d \n", resultm);
                       break;
               case 4: resultr=resta(num1,num2);
                       printf("El resultado es: %d \n", resultr);
                       break; }
     printf("Elija una de las siguientes opciones: \n");
     printf (" 1-Suma \n 2-Division \n 3-Multiplicacion \n 4-Resta \n 0-Salir \n");
     scanf("%d",&op); }
    
    system("PAUSE");
    return 0;
    }
    
    void suma (int a,int b,int *punts)
     {  
      *punts=a+b; }
    
     void divi (int a,int b,int *puntd)
      {
       *puntd=a/b; }
    
     int * multi (int a,int b)
      {
      int *r;
    
    
    r=(a*b);
    return r; }
    
    int * resta (int a,int b)
     {
      int *rr;
    
    rr=(a-b);
    return rr; }   
    
        
    asked by Maca Igoillo 30.01.2017 в 23:15
    source

    2 answers

    1

    First, what is wrong in multi( ) , being applicable to resta( ) :

    int * multi (int a, int b ) {
      int *r;
    
      r = ( a * b );
    
      return r;
    }
    

    By doing r = ( a * b ) , you are assigning to a pointer the result of a multiplication. Although force the compiler to accept it, the result will be, at least, undefined ; you are making the pointer point to an arbitrary address, which I think is not what you intend.

    Note the difference between assigning to a pointer or to the targeted data ; is not the same. In other parts of your code, as *punts = a + b you do it right, you assign the value to the targeted data . The asterisk (*) in front of the variable marks the difference . Without it, you assign to the pointer . With it, you assign to the targeted data .

    Advantages of doing so: in your code, absolutely none. In other cases, it only depends on your imagination. Think, for example, of the function malloc( ) , which assigns memory blocks. How would you do it without returning a pointer? (OK, it's a trick question, it could be done with pointers to pointers **). A very common use is in functions that create and initialize struct or other TAD (Abstract Data Type), and return pointers to the created data.

    From what I gather from the code, the goal of the exercise is to reuse the same variable resultado for all operations , and practice with the possible ways to use it using pointers: passing a pointer as an argument, or returning a pointer as a result.

    My version of the same exercise. As exercise :-p, look for my changes and try to understand them according to what is said here; I see in your code that you already use everything you need (except the do ):

    #include <stdio.h>
    
    int results; // FUERA de main, para que sea accesible por todas las funciones.
    
    void suma( int, int, int * );
    void divi( int, int, int * );
    int *multi( int, int ); 
    int *resta( int, int );
    
    int main( ) {
      int num1, num2, op;
    
      printf( "Ingrese el primer numero:  " );
      scanf( "%d", &num1 );
    
      printf( "Ingrese el segundo numero:  " );
      scanf( "%d", &num2 ); 
    
      do {
        printf( "Elija una de las siguientes opciones: \n" );
        printf( " 1-Suma \n 2-Division \n 3-Multiplicacion \n 4-Resta \n 0-Salir \n" );
        scanf( "%d", &op );
    
        switch( op ) {
        case 1:
          suma( num1, num2, &results );
          printf( "El resultado es: %d \n", results );
          break;
    
        case 2:
          divi( num1, num2, &results );
          printf( "El resultado es: %d \n", results );
          break;
    
        case 3:
          printf("El resultado es: %d \n", *multi( num1, num2 ) );
          break;
    
        case 4:
          printf("El resultado es: %d \n", *resta( num1, num2 ) );
          break;
        }
      } while( op );
    
      system( "PAUSE" );
      return 0;
    }
    
    void suma( int a, int b, int *punts ) {  
      *punts = a + b;
    }
    
    void divi( int a, int b, int *puntd ) {
      *puntd = a / b;
    }
    
    int *multi( int a, int b ) {
      results = a * b;
      return &results;
    }
    
    int *resta( int a, int b ) {
      results = a - b;
      return &results;
    }
    

    Pd .: I know, I'm very picky with the code format xD.

    EDITO

    Working with pointers is the same as working with normal data. We can only assign a value to a variable of the correct type. The main thing is to remember that pointer to int is a type in itself:

    int a = 10; // tipo de a -> int
    int *b = &a; // tipo de b -> puntero a int
    char *str = "hola, mundo !!"; // tipo de str -> puntero a caracter
    
    int c = a; // mismo tipo
    
    int d = b; // NO. TIPOS DISTINTOS.
    
    int *z = b; // mismo tipo
    
    char ch1 = str; // NO. TIPOS DISTINTOS.
    
    char ch2 = *str; // mismo tipo
    

    I add a small example; a function swapInt( ) that exchanges the value of 2 int using pointers; returns 0 if the data is equal , 1 if are different .

    #include <stdio.h>
    
    int swapInt( int *, int * );
    
    int main( void ) {
      int dato1 = 10, dato2 = 20;
      int inter;
    
      printf( "dato1 = %d, dato2 = %d\n", dato1, dato2 );
    
      inter = swapInt( &dato1, &dato2 );
    
      printf( "dato1 = %d, dato2 = %d, se intercambiaron: %d\n", dato1, dato2, inter );
    
      return 0;
    }
    
    void swapInt( int *a, int *b ) {
      int tmp;
    
      // Comparamos los punteros.
      if( a == b )
        return 0;
    
      // Comparamos los valores de los datos apuntados.
      if( *a == *b )
        return 0;
    
      tmp = *a; // tmp == 10.
      a = *b;   // a == 20.
      *b = tmp; // b == 10.
    
      return 1;
    }
    
        
    answered by 31.01.2017 / 00:04
    source
    1
      

    What is the benefit of the function returning a pointer and not a variable of type int with the result?

    In a final program, it does not benefit you at all. Using variables by value is much simpler and faster than using them via pointer. In addition, dynamic memory usually comes into play with pointers and this is often a source of considerable problems.

    However, we must not forget that right now you are learning and during the learning you have to internalize how the language works and that includes the use of pointers and dynamic memory management and that is precisely the purpose of these exercises.

      

    I do not understand very well how the system works to return pointers by means of functions

    The pointers are still variable. A pointer is just that, instead of storing a direct value it does the same with memory addresses ... in fact you could do the following:

    int* ptr;
    ptr = 5;
    printf("%d",ptr); // 5
    

    It is certainly neither the cleanest nor the most recommended use for the case of pointers but it serves to demonstrate that they do not cease to be variables of use.

    Since pointers store memory addresses instead of values or results, their main utility is that they allow information to be shared between different processes. As we see in the following example, this is not possible without pointers:

    void Incrementa(int var)
    { var++; }
    
    void Decrementa(int var)
    { var--; }
    
    void IncrementaPtr(int* var)
    { *var++; }
    
    void DecrementaPtr(int* var)
    { *var--; }
    
    int main()
    {
      int variable = 0;
      Incrementa(variable);
      Incrementa(variable);
      printf("%d\n",variable); // 0
    
      Decrementa(variable);
      printf("%d\n",variable); // 0
    
      IncrementaPtr(&variable);
      IncrementaPtr(&variable);
      printf("%d\n",variable); // 2
    
      DecrementaPtr(&variable);
      printf("%d\n",variable); // 1
    }
    

    As you can see, the functions that do not use pointers do not allow modifying the value stored in the variable, while those that use pointers are able to modify the value of the variable located in the function main() .

    Another advantage of the pointers is that they are able to store lists of elements:

    int lista[100];
    

    The previous variable is, really, a pointer. It is worth mentioning that, due to how it is declared, it has certain limitations with respect to normal pointers, but it is still a pointer. What is happening in the previous line is that the system reserves 100 consecutive positions of type int and makes the pointer lista point to the first of them. Thus, to access any item in the list, it is sufficient to apply a determined displacement. Thus, the following operations are equivalent:

    int valor;
    
    valor = lista[5]; // Acceso por índice
    
    valor = *(lista+5); // Aritmética de punteros
    
    valor = *(5+lista); // Aritmética de punteros 
    
    valor = 5[lista]; // Acceso por índice, funciona pero no te la recomiendo ;)
    

    Why do I tell you this pain in the ass?

    Because it is necessary to know the different utilities of the pointers before understanding what happens when returning a pointer.

    If you have a variable and return it with a return ... what happens? That said value is copied to the variable that captures the return :

    int func()
    { return 5; }
    
    int main()
    {
      int var = func(); // var captura el return
      printf("%d",var);
    }
    

    If instead of a variable you return a pointer, what happens? The memory address is copied:

    int* func()
    { return 5; } // Aquí puede que aparezca un warning
    
    int main()
    {
      int* var = func();
      printf("%d",var);
    }
    

    Now, returning pointers has certain limitations and complications:

  • Unable to return an array of fixed size:

    int* func()
    {
      int lista[100];
      return lista; // ERROR!!!!
    }
    
  • Beware of dereferenced variables:

    int* func()
    {
      int valor = 10;
      return &valor;
    }
    
    int main()
    {
      int* var = func();
      printf("%d",*var); // Cuidado!!! la variable valor ya no existe!!!
    }
    
  • Beware of memory leaks (dynamic memory that is created and not destroyed)

    int* func()
    {
      int* ptr = (int*)malloc(5*sizeof(int));
      return ptr;
    }
    
    int main()
    {
      int* var = func();
    
      var = func(); // La primera reserva de memoria la has perdido!!!!
      free(var);
    }
    
  •   

    The question is that he asks me for these two prototypes of functions: int * multi (int, int); int * subtraction (int, int);

    In this case, it tells me that you are being asked to work with dynamic memory:

    int* multi(int a, int b)
    {
      int* ptr = (int*)malloc(sizeof(int)); // Reservamos espacio para un único elemento
      *ptr = a*b;
      return ptr;
    }
    
    int main()
    {
      int* ptr = multi(3,4);
      printf("%d",*ptr);
      free(ptr);
    }
    

    As I said at the beginning is not the most elegant or the most recommended way to address this problem in a real solution ... but we must not forget that now you are learning and this is one more phase of this process.

        
    answered by 31.01.2017 в 09:45