El tratamiento de C de las matrices es muy diferente al de Java, y tendrá que ajustar su pensamiento en consecuencia. Las matrices en C no son objetos de primera clase (es decir, una expresión de matriz no retiene su "matriz" en la mayoría de los contextos). En C, una expresión de tipo "matriz de elementos N de T
" se convertirá implícitamente ("decaimiento") en una expresión de tipo "puntero a T
", excepto cuando la expresión de matriz sea un operando de los operadores sizeof
unarios &
, o si el La expresión de matriz es un literal de cadena que se utiliza para inicializar otra matriz en una declaración.
Entre otras cosas, esto significa que no puede pasar una expresión de matriz a una función y recibirla como un tipo de matriz ; la función realmente recibe un tipo de puntero:
void foo(char *a, size_t asize)
{
// do something with a
}
int bar(void)
{
char str[6] = "Hello";
foo(str, sizeof str);
}
En la llamada a foo
, la expresión str
se convierte de tipo char [6]
a char *
, razón por la cual foo
se declara el primer parámetro de en char *a
lugar de char a[6]
. En sizeof str
, dado que la expresión de matriz es un operando del sizeof
operador, no se convierte en un tipo de puntero, por lo que obtiene el número de bytes en la matriz (6).
Si está realmente interesado, puede leer El desarrollo del lenguaje C de Dennis Ritchie para comprender de dónde proviene este tratamiento.
El resultado es que las funciones no pueden devolver tipos de matriz, lo cual está bien ya que las expresiones de matriz tampoco pueden ser el objetivo de una asignación.
El método más seguro es que la persona que llama defina la matriz y pase su dirección y tamaño a la función que se supone que debe escribirle:
void returnArray(const char *srcArray, size_t srcSize, char *dstArray, char dstSize)
{
...
dstArray[i] = some_value_derived_from(srcArray[i]);
...
}
int main(void)
{
char src[] = "This is a test";
char dst[sizeof src];
...
returnArray(src, sizeof src, dst, sizeof dst);
...
}
Otro método es que la función asigne la matriz dinámicamente y devuelva el puntero y el tamaño:
char *returnArray(const char *srcArray, size_t srcSize, size_t *dstSize)
{
char *dstArray = malloc(srcSize);
if (dstArray)
{
*dstSize = srcSize;
...
}
return dstArray;
}
int main(void)
{
char src[] = "This is a test";
char *dst;
size_t dstSize;
dst = returnArray(src, sizeof src, &dstSize);
...
free(dst);
...
}
En este caso, la persona que llama es responsable de desasignar la matriz con la free
función de biblioteca.
Tenga dst
en cuenta que en el código anterior hay un puntero simple a char
, no un puntero a una matriz de char
. La semántica de puntero y matriz de C es tal que puede aplicar el operador de subíndice []
a una expresión de tipo de matriz o tipo de puntero; ambos src[i]
y dst[i]
accederá al i
elemento 'th de la matriz (aunque solo src
tenga un tipo de matriz).
Usted puede declarar un puntero a una matriz de n elementos de T
y hacer algo similar:
char (*returnArray(const char *srcArr, size_t srcSize))[SOME_SIZE]
{
char (*dstArr)[SOME_SIZE] = malloc(sizeof *dstArr);
if (dstArr)
{
...
(*dstArr)[i] = ...;
...
}
return dstArr;
}
int main(void)
{
char src[] = "This is a test";
char (*dst)[SOME_SIZE];
...
dst = returnArray(src, sizeof src);
...
printf("%c", (*dst)[j]);
...
}
Varios inconvenientes con lo anterior. En primer lugar, las versiones anteriores de C esperan SOME_SIZE
ser una constante de tiempo de compilación, lo que significa que la función solo funcionará con un tamaño de matriz. En segundo lugar, debe desreferenciar el puntero antes de aplicar el subíndice, que satura el código. Los punteros a matrices funcionan mejor cuando se trata de matrices multidimensionales.