Eu sou relativamente novo em C e preciso de ajuda com métodos para lidar com matrizes. Vindo da programação Java, estou acostumado a ser capaz de dizer int [] method()
para retornar uma matriz. No entanto, descobri que com C você precisa usar ponteiros para matrizes quando as devolve. Sendo um novo programador, eu realmente não entendo nada disso, mesmo com os muitos fóruns que examinei.
Basicamente, estou tentando escrever um método que retorne uma matriz de caracteres em C. Fornecerei o método (vamos chamá-lo de returnArray) com uma matriz. Ele criará uma nova matriz a partir da matriz anterior e retornará um ponteiro para ela. Eu só preciso de alguma ajuda sobre como começar e como ler o ponteiro, uma vez que é enviado para fora da matriz. Qualquer ajuda para explicar isso é apreciada.
Formato de código proposto para a função de retorno de matriz
char *returnArray(char array []){
char returned [10];
//methods to pull values from array, interpret them, and then create new array
return &(returned[0]); //is this correct?
}
Chamador da função
int main(){
int i=0;
char array []={1,0,0,0,0,1,1};
char arrayCount=0;
char* returnedArray = returnArray(&arrayCount); ///is this correct?
for (i=0; i<10;i++)
printf(%d, ",", returnedArray[i]); //is this correctly formatted?
}
Ainda não testei isso, pois meu compilador C não está funcionando no momento, mas gostaria de descobrir isso
Respostas:
Você não pode retornar matrizes de funções em C. Você também não pode (não deveria) fazer isso:
returned
é criado com duração de armazenamento automático e as referências a ele se tornam inválidas quando deixar seu escopo de declaração, ou seja, quando a função retornar.Você precisará alocar dinamicamente a memória dentro da função ou preencher um buffer pré-alocado fornecido pelo chamador.
Opção 1:
alocar dinamicamente a memória dentro da função (responsável pela desalocação
ret
)Chame assim:
Opção 2:
preencher um buffer pré-alocado fornecido pelo chamador (o chamador aloca
buf
e passa para a função)E chame assim:
fonte
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 paraT
", exceto quando a expressão da matriz for um operando dossizeof
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:
Na chamada para
foo
, a expressãostr
é convertida do tipochar [6]
parachar *
, e é por isso que o primeiro parâmetro defoo
é declarado emchar *a
vez dechar a[6]
. Emsizeof str
, como a expressão da matriz é um operando dosizeof
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:
Outro método é a função alocar a matriz dinamicamente e retornar o ponteiro e o tamanho:
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 parachar
, não um ponteiro para uma matriz dechar
. 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; ambossrc[i]
edst[i]
acessarão oi
'ésimo elemento da matriz (mesmo que apenassrc
tenha um tipo de matriz).Você pode declarar um ponteiro para uma matriz de elementos N
T
e fazer algo semelhante: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.fonte
bar
recebe é um ponteiro, não uma matriz. No contexto de uma declaração de parâmetro de funçãoT a[N]
eT a[]
são tratados comoT *a
.void returnArray(const char *srcArray, size_t srcSize, char *dstArray, char dstSize)
último parâmetro deve estar nosize_t
tipo nãochar
.Não estou dizendo que esta é a melhor solução ou a solução preferida para o problema em questão. No entanto, pode ser útil lembrar que as funções podem retornar estruturas. Embora as funções não possam retornar matrizes, elas podem ser agrupadas em estruturas e a função pode retornar a estrutura, transportando a matriz com ela. Isso funciona para matrizes de comprimento fixo.
Convido comentários sobre os pontos fortes e fracos desta técnica. Eu não me incomodei em fazê-lo.
fonte
CHAR_ARRAY returned
o heap? Certamente não pode na pilha (no quadro de pilha dareturnArray()
direita?Que tal essa implementação deliciosamente má?
array.h
main.c
fonte
struct
como um contêiner / objeto de matriz. Pense nisso como um C ++ std :: vector. O pré-processador expandiria aint
versão disso parastruct intArray { int* contents; int size; };
.No seu caso, você está criando uma matriz na pilha e depois de deixar o escopo da função, a matriz será desalocada. Em vez disso, crie uma matriz alocada dinamicamente e retorne um ponteiro para ela.
fonte
new
operador em C. Isso é C ++.sizeof(char)
é garantido que é1
, portanto, neste caso, você pode largar esse pedaçomalloc
.&arr
. Você querarr
ser umchar *
e passá-lo usandoarr
.Você pode fazer isso usando a memória heap (através da chamada malloc () ) como outras respostas relatadas aqui, mas sempre deve gerenciar a memória (use a função free () sempre que chamar sua função). Você também pode fazer isso com uma matriz estática:
Você pode usá-lo sem se preocupar com o gerenciamento de memória.
Neste exemplo, você deve usar a palavra-chave estática na definição de matriz para definir a duração da vida útil da matriz para o aplicativo, para que não seja destruída após a declaração de retorno. Obviamente, dessa maneira, você ocupa SIZE bytes em sua memória por toda a vida útil do aplicativo, então dimensione-o corretamente!
fonte
Seu método retornará uma variável de pilha local que falhará mal. Para retornar uma matriz, crie uma fora da função, passe-a por endereço para a função, modifique-a ou crie uma matriz na pilha e retorne essa variável. Ambos funcionarão, mas o primeiro não requer nenhuma alocação de memória dinâmica para fazê-lo funcionar corretamente.
fonte
Você pode usar código como este:
Quando você faz isso, a memória deve ser liberada posteriormente, passando o endereço para liberar.
Existem outras opções. Uma rotina pode retornar um ponteiro para uma matriz (ou parte de uma matriz) que faz parte de alguma estrutura existente. O chamador pode passar uma matriz e a rotina simplesmente grava na matriz, em vez de alocar espaço para uma nova matriz.
fonte