C++ Pasar puntero a función (Cómo) + Manipulación de puntero C++

11 minutos de lectura

Estoy un poco confundido en cuanto a cómo funcionan los punteros de paso.

Digamos que tengo la siguiente función y puntero, y…

EDITAR:

…Quiero usar un puntero a algún objeto como argumento en la función.

es decir:

void Fun(int Pointer){
    int Fun_Ptr = ---Passed Pointer---; 
    //So that Fun_Ptr points to whatever ---Passed Pointer points to

Entre las notaciones *Pointer y &Pointer, estoy muy confundido. Sé que *Puntero significa dar lo que sea que apunte.

¿Pongo vacío (int * puntero) en la declaración? ¿Qué pasa cuando uso la función?

Su ayuda es apreciada.

EDITAR 2:

Bien, ahora entiendo que usar *variable en una declaración significa que se pasará un puntero. Sin embargo, ¿qué pasa cuando uso la función?

es decir

int main(){
    int foo;
    int *bar;
    bar = foo;
    Fun(bar);
}

EDITAR 3:
Bien, entonces corrígeme si me equivoco:

De acuerdo con las convenciones del código anterior:

bar = &foo significa: hacer que la barra apunte a foo en la memoria

*bar = foo significa Cambiar el valor al que apunta la barra para igualar lo que sea igual a foo

Si tengo un segundo puntero (int *oof), entonces:

bar = oof significa: la barra apunta al puntero oof

bar = *oof significa: bar apunta al valor al que apunta oof, pero no al puntero oof en sí

*bar = *oof significa: cambiar el valor al que apunta la barra al valor al que apunta oof

&bar = &oof significa: cambiar la dirección de memoria a la que apunta la barra para que sea la misma que la dirección de memoria a la que apunta oof

¿Tengo este derecho?

EDIT 4: Muchas gracias por toda su ayuda (Desearía poder aceptar más de 1 respuesta, pero tengo que ir con la primera. No estoy seguro de cómo funciona exactamente un wiki comunitario, pero lo dejaré así por edición (no dude en convertirlo en una guía de referencia si lo desea).

  • Su segunda edición es casi correcta, sin embargo

    – Tomás

    26 de septiembre de 2010 a las 1:13

  • “¿Es eso correcto?”. No, no quieres bar ser igual a fooquieres que apunta a foo. Esto se hace con el operador address-of. bar = &foo;.

    –Steve Jessop

    26 de septiembre de 2010 a las 1:14

  • bar = foo, no es válido, ya que foo es un int y bar un puntero. El código correcto es “bar = &foo” porque como puntero, bar solo puede almacenar direcciones de memoria, no un int. Perdón por las respuestas de los comentarios.

    – Tomás

    26 de septiembre de 2010 a las 1:14


  • Recuerde, bar apunta a la variable foo, por lo que si cambia foo, porque bar solo hace referencia a foo, la próxima vez que use bar también reflejará este cambio.

    – Tomás

    26 de septiembre de 2010 a las 1:25


  • Se movió el comentario eliminado para cuestionarse a sí mismo, por lo que el comentario anterior se deja colgado (lo siento)

    – Biosci3c

    26 de septiembre de 2010 a las 1:26

Avatar de usuario de Tomás
Tomás

Hay una diferencia en el uso de * cuando está definiendo una variable y cuando la está usando.

En declaración,

int *myVariable;

Significa un puntero a un tipo de datos entero. En uso sin embargo,

*myVariable = 3;

Significa eliminar la referencia del puntero y hacer que la estructura a la que apunta sea igual a tres, en lugar de hacer que el puntero sea igual a la dirección de memoria 0x 0003.

Así que en tu función, quieres hacer esto:

void makePointerEqualSomething(int* pInteger)
{
    *pInteger = 7;
}

En la declaración de la función, * significa que está pasando un puntero, pero en su cuerpo de código real * significa que está accediendo a lo que apunta el puntero.

En un intento de eliminar cualquier confusión que tenga, entraré brevemente en el símbolo de y comercial (&)

& significa obtener la dirección de algo, su ubicación exacta en la memoria de la computadora, por lo que

 int & myVariable;

En una declaración significa la dirección de un número entero, o un puntero!

esto sin embargo

int someData;    
pInteger = &someData;

Significa hacer que el puntero pInteger en sí mismo (recuerde, los punteros son solo direcciones de memoria de lo que apuntan) sea igual a la dirección de ‘someData’, por lo que ahora pInteger apuntará a algunos datos y se puede usar para acceder a ellos cuando lo deferencia:

*pInteger += 9000;

¿Tiene sentido esto para ti? ¿Hay algo más que le resulte confuso?

@Edit3:

Casi correcto, excepto por tres afirmaciones.

bar = *oof;

significa que el puntero de la barra es igual a un número entero, no a lo que apunta la barra, lo cual no es válido.

&bar = &oof;

El ampersand es como una función, una vez que devuelve una dirección de memoria, no puedes modificar su procedencia. Al igual que este código:

returnThisInt("72") = 86; 

no es válido, al igual que el tuyo.

Finalmente,

bar = oof

No significa que “la barra apunte al puntero oof”. Más bien, esto significa que bar apunta a la dirección a la que apunta oof, por lo que bar apunta a lo que foo esté apuntando, no bar apunta a foo que apunta a oof.

  • Bien, ¿eso significa que el puntero pInteger apunta al puntero someData?

    – Biosci3c

    26 de septiembre de 2010 a las 1:14

  • Debería haber aclarado, someData no es un puntero, es un int sin formato. He editado mi respuesta apropiadamente. ¿El símbolo & tiene sentido para ti ahora?

    – Tomás

    26 de septiembre de 2010 a las 1:15


  • De acuerdo, creo que lo tengo un poco bajo (los punteros siempre me confunden, y realmente estoy tratando de entenderlos). Creo que ahora lo tengo bastante bien entendido.

    – Biosci3c

    26 de septiembre de 2010 a las 1:17

Avatar de usuario de JoshD
jose d

Para declarar una función que lleva un puntero a un int:

void Foo(int *x);

Para usar esta función:


int x = 4;
int *x_ptr = &x;
Foo(x_ptr);
Foo(&x);

Si desea un puntero para otro tipo de objeto, es más o menos lo mismo:

void Foo(Object *o);

Pero, es posible que prefiera usar referencias. Son algo menos confusos que los punteros:


// pass a reference
void Foo(int &x)
{
  x = 2;
}

//pass a pointer
void Foo_p(int *p)
{
   *x = 9;
}

// pass by value
void Bar(int x)
{
   x = 7;
}
int x = 4;
Foo(x);  // x now equals 2.
Foo_p(&x); // x now equals 9.
Bar(x);  // x still equals 9.

Con las referencias, aún puede cambiar la x que se pasó a la función (como lo haría con un puntero), pero no tiene que preocuparse por la eliminación de referencias o la dirección de las operaciones.

Según lo recomendado por otros, echa un vistazo a la Preguntas frecuentes de C++. Es un excelente recurso para esto.

Editar 3 respuesta:

bar = &foo significa: hacer que la barra apunte a foo en la memoria

Sí.

*bar = foo significa Cambiar el valor al que apunta la barra para igualar lo que sea igual a foo

Sí.

Si tengo un segundo puntero (int *oof), entonces:

bar = oof significa: la barra apunta al puntero oof

bar apuntará a lo que oof apunte. Ambos apuntarán a lo mismo.

bar = *oof significa: bar apunta al valor al que apunta oof, pero no al puntero oof en sí

No. No puede hacer esto (asumiendo que la barra es de tipo int *) Puede hacer punteros. (int **), pero no entremos en eso… No puedes asignar un puntero a un int (bueno, puedes, pero ese es un detalle que no está en línea con la discusión).

*bar = *oof significa: cambiar el valor al que apunta la barra al valor al que apunta oof

Sí.

&bar = &oof significa: cambiar la dirección de memoria a la que apunta la barra para que sea la misma que la dirección de memoria a la que apunta oof

No. No puede hacer esto porque la dirección del operador devuelve un valor r. Básicamente, eso significa que no puedes asignarle nada.

Avatar de usuario de Steve Jessop
steve jesop

Si desea pasar un puntero a int en su función,

Declaración de función (si la necesita):

void Fun(int *ptr);

Definición de función:

void Fun(int *ptr) {
    int *other_pointer = ptr;  // other_pointer points to the same thing as ptr
    *other_ptr = 3;            // manipulate the thing they both point to
}

Uso de la función:

int main() {
    int x = 2;
    printf("%d\n", x);
    Fun(&x);
    printf("%d\n", x);
}

Nótese como regla general, que las variables llamadas Ptr o Pointer nunca debe tener tipo int, que es lo que tienes entonces en tu código. Un puntero a int tiene tipo int *.

Si tengo un segundo puntero (int *oof), entonces:

bar = oof significa: la barra apunta al puntero oof

Significa “hacer que la barra apunte a lo mismo que oof apunte”.

bar = *oof significa: bar apunta al valor al que apunta oof, pero no al puntero oof en sí

Eso no significa nada, no es válido. bar es un puntero *oof es un int. No se puede asignar uno al otro.

*bar = *oof significa: cambiar el valor al que apunta la barra al valor al que apunta oof

Sí.

&bar = &oof significa: cambiar la dirección de memoria a la que apunta la barra para que sea la misma que la dirección de memoria a la que apunta oof

No, eso no es válido de nuevo. &bar es un puntero a la bar variable, pero es lo que se llama un “rvalue” o “temporal”, y no se le puede asignar. Es como el resultado de un cálculo aritmético. no puedes escribir x + 1 = 5.

Podría ayudarlo pensar en los punteros como direcciones. bar = oof significa “hacer bar, que es una dirección, igual a oof, que también es una dirección”. bar = &foo significa “hacer bar, que es una dirección, igual a la dirección de foo”. Si bar = *oof significaba algo, significaría “hacer bar, que es una dirección, igual a *oofque es un int”. No puedes.

Entonces, & es la dirección del operador. Significa “la dirección del operando”, por lo que &foo es la dirección de foo (es decir, un puntero a foo). * es el operador de desreferencia. Significa “la cosa en la dirección dada por el operando”. Así que habiendo hecho bar = &foo, *bar es foo.

Para pasar un puntero a un int debe ser void Fun(int* pointer).

Pasar una referencia a un int se vería así…

void Fun(int& ref) {
   ref = 10;
}

int main() {
   int test = 5;
   cout << test << endl;  // prints 5

   Fun(test);
   cout << test << endl;  // prints 10 because Fun modified the value

   return 1;
}

void Fun(int *Pointer)
{
  //if you want to manipulate the content of the pointer:
  *Pointer=10;
  //Here we are changing the contents of Pointer to 10
}

* antes del puntero significa el contenido del puntero (¡excepto en las declaraciones!)

& antes del puntero (o cualquier variable) significa la dirección

EDITAR:

int someint=15;
//to call the function
Fun(&someint);
//or we can also do
int *ptr;
ptr=&someint;
Fun(ptr);

  • @ tommieb75: ¿por qué importa que sea C válido? También es sintaxis de C ++, y el interrogador no especificó “C ++, con C eliminado”. Sea lo que sea.

    –Steve Jessop

    26 de septiembre de 2010 a las 1:43


Avatar de usuario de AndersK
andersk

void Fun(int* Pointer)   -- would be called as Fun( &somevariable )

le permitiría manipular el contenido de lo que apunta ‘Puntero’ desreferenciandolo dentro de la función Fun, es decir

*Pointer = 1;

declararlo como arriba también le permite manipular datos más allá de lo que apunta:

int foo[10] = {0};
Fun(foo);

en la función puedes hacer como *(Puntero + 1) = 12; estableciendo el segundo valor de la matriz.

void Fun(int& Pointer)  -- would be called Fun( somevariable )

puede modificar a qué hace referencia el puntero; sin embargo, en este caso no puede acceder a nada más allá de lo que hace referencia el puntero.

  • @ tommieb75: ¿por qué importa que sea C válido? También es sintaxis de C ++, y el interrogador no especificó “C ++, con C eliminado”. Sea lo que sea.

    –Steve Jessop

    26 de septiembre de 2010 a las 1:43


Puede ser más fácil para usted entender el uso de Functionoids que son expresivamente más ordenados y más poderosos de usar, vea este excelente y altamente recomendado Preguntas frecuentes de C++en particular, mire la sección 33.12 en adelante, pero no obstante, léala desde el comienzo de esa sección para comprenderla.

Para responder tu pregunta:

typedef void (*foobar)() fubarfn;

void Fun(fubarfn& baz){
   fubarfn = baz;
   baz();
}

Editar:

  • & significa la dirección de referencia
  • * significa el valor de lo que está contenido en la dirección de referencia, llamado desreferenciar

Entonces, usar la referencia, ejemplo a continuación, muestra que estamos pasando un parámetro y modificándolo directamente.

void FunByRef(int& iPtr){
    iPtr = 2;
}

int main(void){
    // ...
    int n;
    FunByRef(n);
    cout << n << endl; // n will have value of 2
}

  • Tal vez debería aclarar. No estoy tratando de usar un puntero a una función, pero paso un puntero a algún objeto (digamos un int) a la función, para que la función pueda operar en él. Voy a revisar mi pregunta para aclarar esto.

    – Biosci3c

    26 de septiembre de 2010 a las 1:06

¿Ha sido útil esta solución?