Pasar estructura a función

6 minutos de lectura

avatar de usuario
daniel del core

Soy un nuevo programador de C y quería saber cómo puedo pasar un struct a través de una función. Recibo un error y no puedo descifrar la sintaxis correcta para hacerlo. Aquí está el código para ello….

Estructura:

struct student{
    char firstname[30];
    char surname[30];
};

struct student person;

Llamada:

addStudent(person);

Prototipo:

void addStudent(struct student);

y la función real:

void addStudent(person)
{
    return;
}

Errores del compilador:

línea 21: advertencia: declaración de etiqueta dudosa: struct estudiante
línea 223: el argumento #1 es incompatible con el prototipo:

  • ¿Dónde estás declarando tu estructura? En su archivo de implementación real, ¿dónde está su struct student { /* ... */ }; ¿código? Parece que está en el ámbito incorrecto (como declarado en su main función o cualquier función que estés tratando de llamar addStudent desde…

    –Jason Coco

    29 de abril de 2012 a las 6:04

  • sí, está en el alcance de mi función

    –Daniel Del Core

    29 de abril de 2012 a las 6:06

avatar de usuario
Donnell

Así se pasa el struct por referencia. Esto significa que su función puede acceder a la struct fuera de la función y modificar sus valores. Para ello, pasa un puntero a la estructura de la función.

#include <stdio.h>
/* card structure definition */
struct card
{
    int face; // define pointer face
}; // end structure card

typedef struct card Card ;

/* prototype */
void passByReference(Card *c) ;

int main(void)
{
    Card c ;
    c.face = 1 ;
    Card *cptr = &c ; // pointer to Card c

    printf("The value of c before function passing = %d\n", c.face);
    printf("The value of cptr before function = %d\n",cptr->face);

    passByReference(cptr);

    printf("The value of c after function passing = %d\n", c.face);

    return 0 ; // successfully ran program
}

void passByReference(Card *c)
{
    c->face = 4;
}

Así se pasa el struct por valor para que su función reciba una copia de la struct y no puede acceder a la estructura exterior para modificarla. Por exterior quiero decir fuera de la función.

#include <stdio.h>


/* global card structure definition */
struct card
{
    int face ; // define pointer face
};// end structure card

typedef struct card Card ;

/* function prototypes */
void passByValue(Card c);

int main(void)
{
    Card c ;
    c.face = 1;

    printf("c.face before passByValue() = %d\n", c.face);

    passByValue(c);

    printf("c.face after passByValue() = %d\n",c.face);
    printf("As you can see the value of c did not change\n");
    printf("\nand the Card c inside the function has been destroyed"
        "\n(no longer in memory)");
}


void passByValue(Card c)
{
    c.face = 5;
}

  • conciso. Con buena pinta.

    – Reynal Gobel

    7 de diciembre de 2015 a las 5:43

  • Absolutamente perfecto !

    – StrawHara

    24/03/2016 a las 19:27

  • Un poco tarde para preguntar, pero ¿por qué escribir la estructura con el mismo nombre (pero con mayúscula)? También me pregunto por qué necesita crear un puntero a la estructura (*cptr), luego use eso para pasar a la función, cuando podría pasar la estructura de la tarjeta original por referencia usando &c. Soy nuevo en las estructuras en C, así que realmente busco comentarios.

    – Matt K.

    4 de agosto de 2021 a las 16:59

  • Buen código, excelente explicación.

    –Arjuna Deva

    17 de noviembre de 2021 a las 14:34

  • @MattK Typdefing con el mismo nombre nos permitiría definir estructuras de instancias sin el struct palabra clave. Por ejemplo, este ejemplo sin el typedef: struct card card1 = {...};. Con typedef: card card1 = {...};. La letra mayúscula y la creación del puntero son solo preferencia (convención/legibilidad) AFAIK.

    – Wadite RK

    23 de febrero a las 20:31

avatar de usuario
MByD

La implementación de la función de línea debe ser:

void addStudent(struct student person) {

}

person no es un tipo sino una variable, no puede usarlo como el tipo de un parámetro de función.

Además, asegúrese de que su estructura esté definida antes que el prototipo de la función. addStudent como lo usa el prototipo.

  • Una buena idea es “nombrar” el tipo de estructura para evitar este problema, usando typedef. Ver en.wikipedia.org/wiki/Struct_(C_programming_language)

    – Jouni Aro

    29 de abril de 2012 a las 5:58


  • ¿Eso significa que tengo que sacar toda la estructura de mi función y ponerla en mi archivo de encabezado donde están los prototipos?

    –Daniel Del Core

    29 de abril de 2012 a las 6:04


  • @DanielDC – Tenía miedo de preguntar esto. Sí, la estructura debe declararse en un ámbito global, ya que también la utilizan otras funciones.

    – MByD

    29 de abril de 2012 a las 6:06

  • ohk, pensé que podrías usarlo de la misma manera que ints y chars. ;( que verguenza… gracias por tu ayuda

    –Daniel Del Core

    29 de abril de 2012 a las 6:09

  • De nada, no te lo tomes a mal, no es baladí cuando empiezas con el idioma.

    – MByD

    29 de abril de 2012 a las 6:10

avatar de usuario
tom1990

Al pasar una estructura a otra función, generalmente sería mejor hacer lo que Donnell sugirió anteriormente y pasarla por referencia.

Una muy buena razón para esto es que facilita las cosas si desea realizar cambios que se reflejarán cuando regrese a la función que creó la instancia.

Aquí hay un ejemplo de la manera más simple de hacer esto:

#include <stdio.h>

typedef struct student {
    int age;
} student;

void addStudent(student *s) {
    /* Here we can use the arrow operator (->) to dereference 
       the pointer and access any of it's members: */
    s->age = 10;
}

int main(void) {

    student aStudent = {0};     /* create an instance of the student struct */
    addStudent(&aStudent);      /* pass a pointer to the instance */

    printf("%d", aStudent.age);

    return 0;
}

En este ejemplo, el argumento a favor de la addStudent() La función es un puntero a una instancia de un student estructura – student *s. En main()creamos una instancia del student estructura y luego pasar una referencia a ella a nuestro addStudent() función usando el operador de referencia (&).

En el addStudent() función podemos hacer uso del operador de flecha (->) para desreferenciar el puntero y acceder a cualquiera de sus miembros (funcionalmente equivalente a: (*s).age).

Cualquier cambio que hagamos en el addStudent() la función se verá reflejada cuando volvamos a main()porque el puntero nos dio una referencia a donde en la memoria la instancia de la student la estructura está siendo almacenada. Esto es ilustrado por el printf()que generará “10” en este ejemplo.

Si no hubiera pasado una referencia, en realidad estaría trabajando con una copia de la estructura que pasó a la función, lo que significa que cualquier cambio no se reflejaría cuando regrese a main – ¡a menos que haya implementado una forma de pasar la nueva versión de la estructura a la principal o algo por el estilo!

Aunque los punteros pueden parecer desagradables al principio, una vez que entiendes cómo funcionan y por qué son tan útiles, se convierten en una segunda naturaleza, ¡y te preguntas cómo te las arreglaste sin ellos!

Debe especificar un tipo de persona:

void addStudent(struct student person) {
...
}

Además, puede tipear su estructura para evitar tener que escribir struct cada vez que la use:

typedef struct student{
...
} student_t;

void addStudent(student_t person) {
...
}

En lugar de:

void addStudent(person)
{
    return;
}

prueba esto:

void addStudent(student person)
{
    return;
}

Como ya ha declarado una estructura llamada ‘estudiante’, no necesariamente tiene que especificarlo en la implementación de la función como en:

void addStudent(struct student person)
{
    return;
}

  • No lo creo. Sin typedef, sale en error.

    – Abdilah

    21 de julio de 2014 a las 0:47

  • No lo creo. Sin typedef, sale en error.

    – Abdilah

    21 de julio de 2014 a las 0:47

¿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