una retornar retorna puntero como cadena c pointers struct

como - retornar un puntero en c



DevoluciĆ³n de un puntero estructural (6)

Supongamos que tengo la siguiente estructura y función devolviendo un puntero:

typedef struct { int num; void *nums; int size; } Mystruct; Mystruct *mystruct(int num, int size) { //Is the following correct? Is there a more efficient way? Mystruct mystruct; mystruct.num = num; mystruct.size = size; mystruct.nums = malloc(num*sizeof(size)); Mystruct *my; *my = mystruct; return my; }

Quiero definir cualquier puntero Mystruct usando la función anterior. ¿Debo declarar una variable Mystruct, definir las propiedades de Mystruct, asignarle un puntero y devolver el puntero o definir las propiedades de una propiedad mystruct a través de un puntero inmediatamente?


Si declaro una variable Mystruct, defino las propiedades de Mystruct, le asigno un puntero y devuelvo el puntero

Definitivamente no, porque la variable definida en la función (en la clase de almacenamiento "automático") desaparecerá cuando la función salga, y usted devolverá un puntero colgante.

Puede aceptar un puntero a un Mystruct (la responsabilidad del que llama para asignarlo) y completarlo; o puede usar malloc para crear uno nuevo (la responsabilidad del llamador es liberarlo cuando esté listo). La segunda opción al menos le permite mantener la firma de la función en la que parece estar interesado:

Mystruct *mystruct(int num, int size) { Mystruct *p = malloc(sizeof(MyStruct)); .... return p; }

pero a menudo es inferior, ya que la persona que llama debe tener responsabilidades de todos modos, también puede ir con la primera opción y potencialmente obtener rendimiento (si la persona que llama puede usar una instancia de clase automática porque sabe que el alcance de uso está limitado) .


Es importante recordar que el puntero no es algo que le asigna a la estructura, sino que el puntero indica la ubicación en la memoria que desea tratar como una estructura. Según su pregunta, realmente desea asignar la memoria para mantener la estructura de datos. Esto le da un puntero a la ubicación de la memoria asignada. Una vez que tienes eso, puedes devolverlo.

EDITAR (después de editar a la pregunta original) Mirando su edición a la pregunta, definitivamente tendrá problemas con el puntero "mi". Esto no está inicializado, y puede apuntar a cualquier lugar en la memoria. Cuando intente copiar la estructura, probablemente obtenga un seg-fault.


La asignación de un nuevo Mystruct y la devolución de un puntero generalmente se vería más o menos así:

Mystruct *mystruct(int num, int size) { Mystruct *result; result = malloc(sizeof(MyStruct)); if (!result) return NULL; result->num = num; ... return result; }

Más tarde, cuando haya terminado con el Mystruct asignado aquí con malloc , debería liberarse de nuevo con free() .

Solo declarar una variable local y devolver un puntero a esa variable local no funcionará. La variable local sale del alcance al final de la función y es muy probable que la memoria donde se almacenó se reutilice para otros fines. El puntero devuelto seguirá apuntando a la ubicación de la memoria donde una vez estuvo la variable local, pero como esa variable ya no existe, ese puntero no sería de mucha utilidad.


No puede usar la variable porque se desasignará cuando la función finalice. Por ejemplo:

Mystruct *mystruct(int num, int size) { MyStruct x; x.num = 1; ... return &x; }

Otorgará una falla de segmentación o una infracción de acceso porque la memoria para x se desasignará tan pronto como salga. Por lo tanto, debe asignar memoria para la estructura (y asegúrese de liberarla más adelante) o declare un sistema global que permanecerá para siempre. Ejemplo para el último ...

Mystruct *mystruct(int num, int size) { MyStruct *x; x = (MyStruct*)malloc( sizeof( MyStruct ) ); x->num = 1; ... return x; }


Si está escribiendo un código genérico y no sabe cómo se lo puede usar, es bueno brindarle ambas opciones:

int mystructm(Mystruct *storage, int num, int size) { int rv = 0; storage->num = num; storage->size = size; storage->nums = malloc(num*sizeof(size)); if (!storage->nums) return -1; return 0; } Mystruct *mystruct(int num, int size) { Mystruct *mp = (Mystruct *)malloc(sizeof(Mystruct)); if (mp) { if (mystructm(mp, num, size) == -1) { free(mp); mp = NULL; } } return mp; }

La idea es que, como escritor de la biblioteca, no se debe dictar una política (como que cada Mystruct debe asignarse dinámicamente), sino que debe dejar que el escritor de la aplicación lo decida.


Una forma más de hacerlo ...

int mystruct(Mystruct *mystruct, int num, int size){ if(mystruct == NULL) return -1; mystruct->num = num; mystruct->size = size; :: return 0; } int main(){ Mystruct my; if(mystruct(&my, 3, 4) != 0){ fprintf(stderr, "Cannot init!/n"); exit(0); } :: }