O tratamento de C de matrizes é muito diferente do Java, e você terá que ajustar seu pensamento de acordo. Matrizes em C não são objetos de primeira classe (ou seja, uma expressão de matriz não mantém sua "matriz" na maioria dos contextos). Em C, uma expressão do tipo "N-elemento da matriz de T
" será implicitamente convertida ("decaimento") em uma expressão do tipo "ponteiro para T
", exceto quando a expressão da matriz for um operando dos sizeof
operadores ou unários &
, ou se o expressão de matriz é uma cadeia de caracteres literal usada para inicializar outra matriz em uma declaração.
Entre outras coisas, isso significa que você não pode passar uma expressão de matriz para uma função e recebê-la como um tipo de matriz ; a função realmente recebe um tipo de ponteiro:
void foo(char *a, size_t asize)
{
// do something with a
}
int bar(void)
{
char str[6] = "Hello";
foo(str, sizeof str);
}
Na chamada para foo
, a expressão str
é convertida do tipo char [6]
para char *
, e é por isso que o primeiro parâmetro de foo
é declarado em char *a
vez de char a[6]
. Em sizeof str
, como a expressão da matriz é um operando do sizeof
operador, ela não é convertida em um tipo de ponteiro; portanto, você obtém o número de bytes na matriz (6).
Se você estiver realmente interessado, pode ler O desenvolvimento da linguagem C, de Dennis Ritchie, para entender de onde vem esse tratamento.
O resultado é que as funções não podem retornar tipos de matriz, o que é bom, pois as expressões de matriz também não podem ser o destino de uma atribuição.
O método mais seguro é o chamador definir a matriz e passar seu endereço e tamanho para a função que deveria escrever para ela:
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);
...
}
Outro método é a função alocar a matriz dinamicamente e retornar o ponteiro e o tamanho:
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);
...
}
Nesse caso, o chamador é responsável por desalocar a matriz com a free
função de biblioteca.
Observe que dst
no código acima é um ponteiro simples para char
, não um ponteiro para uma matriz de char
. A semântica de ponteiro e matriz de C é tal que você pode aplicar o operador subscrito []
a uma expressão do tipo de matriz ou tipo de ponteiro; ambos src[i]
e dst[i]
acessarão o i
'ésimo elemento da matriz (mesmo que apenas src
tenha um tipo de matriz).
Você pode declarar um ponteiro para uma matriz de elementos N T
e fazer algo semelhante:
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]);
...
}
Várias desvantagens com o acima exposto. Antes de tudo, as versões mais antigas do C esperam SOME_SIZE
ser uma constante em tempo de compilação, o que significa que a função funcionará apenas com um tamanho de matriz. Em segundo lugar, é necessário desreferenciar o ponteiro antes de aplicar o subscrito, o que atrapalha o código. Ponteiros para matrizes funcionam melhor quando você está lidando com matrizes multidimensionais.