¿Cuál es la forma correcta de escribir una función C que devuelve una matriz de char?

StackOverflow https://stackoverflow.com/questions/8311131

  •  25-10-2019
  •  | 
  •  

Pregunta

Estoy bastante familiarizado con Java, no así en C.

En Java, si tengo un método que hace algo y devuelve una cadena, se vería como:

private String doSomething(...) {
    String s;
    // do something;
    return s;
}

El equivalente sintáctico en C no funcionaría y es simplemente incorrecto:

char* doSomething(...) {
    char s[100];
    // do something;
    return s;
}

Por supuesto que puedo hacer:

char* doSomething(...) {
    char *s;
    s = malloc(100 * sizeof(char));
    // do something;
    return s;
}

Lo que funcionaría (¡creo!) Pero rara vez veo códigos haciendo de esta manera (¿es porque está llenando innecesariamente el montón?)

más comúnmente, ya veo:

bool doSomething(char *s) {
    // do something that copies chars to s
    return true;
}

Y las declaraciones de llamadas serían:

char s[100];
doSomething(s);

¿Qué pasa si no sé el tamaño de la matriz de char hasta dentro de la función en sí? es decir, no podría declarar la matriz Char fuera de la función y luego pasarla.

¿Qué sería el correcto ¿Forma de lidiar con tal escenario?

¿Fue útil?

Solución

Un ejemplo de caso de asignación estática (está obligado a pensar en el tamaño máximo del búfer en el tiempo de compilación)

buf[MAX_NO];
do(buf, MAX_NO);

_Bool do(char *s, size_t len) { 
// use len as boundary in your operations
}

o caso de asignación dinámica (usando Malloc como dijo y usando punteros para guardar la ubicación y el tamaño del búfer)

char *s = NULL;
size_t final_len;
do(&s, &final_len);

_Bool do(char** s, size_t* final_len) {
    size_t len = discoverSize();
    char* buf = (char*) malloc(sizeof(char) * len);

    *s = buf; //save memory location
    *final_len = len; //save buffer size
    // use len as boundary in your operations

}

// do whatever
free(s); //remember to free the buffer for politeness

Otros consejos

Deje que el código de llamada sea responsable de asignar la memoria. Pase en el búfer y la longitud del búfer en el ejemplo 2:

bool doSomething(char *s, size_t buflen)
{ 
    // do something that copies chars to s up to max of buflen
    return true; 
} 

Esto tiende a reducir las fugas, ya que el código de llamada tiene el control de la gestión de la memoria.

Para cuando no pueda conocer el tamaño correcto de la cadena devuelta, use el malloc solución. Por supuesto que tienes que free la cadena, después de que termine con ella.

No puede devolver una matriz en C.

Puedes devolver un puntero y deberías aprender (leyendo un buen libro en programación en el C lenguaje) la diferencia entre matrices y punteros.

Un idioma común es devolver un puntero asignado dinámicamente. Entonces debe tener una convención que diga quién liberará el puntero.

También puede devolver una estructura que contenga una matriz.

adenda

Si desea tener un recolector de basura en C, intente Recolector de basura de Boehm

La forma más segura es dejar la responsabilidad de asignar a la persona que llama, como lo dijeron otros.

Pero, si no necesita un código reentrante y la simplicidad de Java, el equivalente de trabajo sintáctico en C es:

char* doSomething(...) {
    static char s[100];
    // do something;
    return s;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top