Cambiar la dirección contenida por el puntero usando la función

5 minutos de lectura

avatar de usuario
pranfia

Si he declarado un puntero p como int *p; en el módulo principal, puedo cambiar la dirección contenida por p asignando p = &a; donde a es otra variable entera ya declarada. Ahora quiero cambiar la dirección usando una función como:

void change_adrs(int*q)
{
    int *newad;
    q = newad;
}

Si llamo a esta función desde el módulo principal

int main()
{
    int *p;
    int a = 0;
    p = &a; // this changes the address contained by pointer p
    printf("The address is %u\n", p);
    change_adrs(p);
    printf("The address is %u\n", p); // but this doesn't change the address
    return 0;
}

el contenido de la dirección no cambia. ¿Qué tiene de malo usar una función para la misma tarea?

  • Está pasando el puntero por valor. Si necesita cambiar el puntero dentro de la función, páselo por referencia… doble puntero.

    – Alok Guardar

    17 de noviembre de 2012 a las 13:43


avatar de usuario
matemático1975

En C, los argumentos de las funciones se pasan por valor. Por lo tanto, se hace una copia de su argumento y el cambio se realiza en esa copia, no en el objeto de puntero real que espera ver modificado. Deberá cambiar su función para aceptar un argumento de puntero a puntero y realizar el cambio en el argumento desreferenciado si desea hacer esto. Por ejemplo

 void foo(int** p) {
      *p = NULL;  /* set pointer to null */
 }
 void foo2(int* p) {
      p = NULL;  /* makes copy of p and copy is set to null*/
 }

 int main() {
     int* k;
     foo2(k);   /* k unchanged */
     foo(&k);   /* NOW k == NULL */
 }

Si tiene el lujo de usar C++, una forma alternativa sería cambiar la función para aceptar una referencia a un puntero.

  • Solo me gustaría señalar que el estándar C no garantiza que asignar p a 0 lo haga nulo.

    – JKRT

    17 de noviembre de 2017 a las 20:28


  • si yo fuera a *arr = malloc() una nueva matriz en la función llamada y el punto **p a eso, es *p = &arr?

    – mlestudiante33

    6 de julio de 2020 a las 5:45

  • @JKRT: 6.2.3.2 en la especificación C dice “Una expresión constante de entero con el valor 0, o una expresión de este tipo convertida en tipo void *, se denomina constante de puntero nulo”. — por lo que asignar un 0 literal lo hará nulo. El ‘o’ en esa oración significa que no es necesario moldear.

    – Chris Dodd

    16 de noviembre de 2020 a las 22:51


En C, las variables se pasan por valor: se pasa una copia del puntero a la función. Use otro puntero al puntero en su lugar:

void change(int **p, int *someOtherAddress)
{
    *p = someOtherAddress;
}

int a = 1, b = 2;
int *p = &a;

printf("*p = %d\n", *p);
change(&p, &b);
printf("*p = %d\n", *p);

esto imprime

*p = 1
*p = 2

  • Vote a favor simplemente porque esta respuesta evita la frase “doble puntero”

    – William Pursell

    5 de agosto de 2020 a las 22:49

avatar de usuario
gruñido

Si desea modificar el contenido de una variable en una función en C, el puntero también es un tipo de variable, debe pasarlo por puntero o referencia indirecta usando siempre & dirección y * operadores de desreferencia. quiero decir * El operador siempre se usa y va precedido al cambiar el valor de una variable.

#include <stdio.h>
#include <stdlib.h>


void changeIntVal(int *x) {
    *x = 5;
}

void changePointerAddr(int **q) {
    int *newad;
    *q = newad;
}

void changePPAddr(int ***q) {
    int **dummy;
    *q = dummy;
}

int main() {
    int *p;
    int **pp;
    int *tempForPP;
    int a = 0;
    printf("\n The address pointing by p -> %p, pp -> %p, value of a -> %d ", p, pp, a);


    p = &a;
    pp = &tempForPP;
    printf("\n The address pointing by p -> %p, pp -> %p, value of a -> %d ", p, pp, a);

    changeIntVal(&a);        // ----
                             //    |---
    changePointerAddr(&p);   // ----  |---->  parts of what I mean
                             //    |---
    changePPAddr(&pp);       // ----

    printf("\n The address pointing by p -> %p, pp -> %p, value of a -> %d ", p, pp, a);

    return 0;

}

Para un tipo de datos primitivo como un int, los punteros dobles no son necesarios. Puede escribir directamente a la dirección donde se encuentra el int se almacena, tratando su dirección como un puntero en la función que se llama. Esto es diferente a un char matriz (“cadena”) donde el tamaño de lo que se apunta es variable y, por lo tanto, debe usar otro nivel de direccionamiento indirecto al cambiarlo desde dentro de una función llamada. Prueba esto:

void foo(int *oldVal)
{
    int newVal = 99;    // or whatever you want
    *oldVal = newVal;
}

int main(int argc, char *argv[])
{
    int someVal = 0;
    foo(&someVal);      // we send its address to foo()

    printf("someVal is now %d.\n", someVal);

    return EXIT_SUCCESS;
}

avatar de usuario
Omkant

Esto no cambiará el valor real de p porque el q en función es local a eso y el cambio en esa función no se reflejará en main así que pasa la dirección de p en lugar de pasar p por valor

Use esta sintaxis a continuación

void change_adrs(int **q)
{
    int * otheraddess;
    *q = otheraddress; 
}

y llamar asi change_adrs(&p);

O bien, tiene otra forma: cambie el tipo de devolución de la función y capture la dirección devuelta.

int* change_adrs(int *q)
{
    int * otheraddess;
    q = otheraddress;
    return q; 
}


int main()
{
    p = change_adrs(p);
    return 0;
}

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad