Passando uma matriz como um argumento para uma function em C

Eu escrevi uma function contendo array como argumento, e chamei passando o valor do array da seguinte maneira.

void arraytest(int a[]) { // changed the array a a[0]=a[0]+a[1]; a[1]=a[0]-a[1]; a[0]=a[0]-a[1]; } void main() { int arr[]={1,2}; printf("%d \t %d",arr[0],arr[1]); arraytest(arr); printf("\n After calling fun arr contains: %d\t %d",arr[0],arr[1]); } 

O que eu encontrei é que estou chamando function arraytest() passando valores, a cópia original de int arr[] é alterada.

Você pode por favor explicar por quê?

Ao passar um array como parâmetro,

 void arraytest(int a[]) 

significa exatamente o mesmo que

 void arraytest(int *a) 

então você está modificando os valores no main.

Por razões históricas, os arrays não são cidadãos de primeira class e não podem ser passados ​​por valor.

Você não está passando a matriz como cópia. É apenas um ponteiro apontando para o endereço onde o primeiro elemento está na memory.

Você está passando o endereço do primeiro elemento da matriz

Em C, com exceção de alguns casos especiais, uma referência de matriz sempre “decai” para um ponteiro para o primeiro elemento da matriz. Portanto, não é possível transmitir uma matriz “por valor”. Uma matriz em uma chamada de function será passada para a function como um ponteiro, que é análogo a passar a matriz por referência.

EDIT: Existem três casos especiais em que uma matriz não decai para um ponteiro para o primeiro elemento:

  1. sizeof a não é o mesmo que sizeof (&a[0]) .
  2. &a não é o mesmo que &(&a[0]) (e não é o mesmo que &a[0] ).
  3. char b[] = "foo" não é o mesmo que char b[] = &("foo") .

Você está passando o valor da localização da memory do primeiro membro da matriz.

Portanto, quando você começa a modificar a matriz dentro da function, você está modificando a matriz original.

Lembre-se que a[1] é *(a+1) .

Se você quiser passar uma matriz unidimensional como um argumento em uma function , você teria que declarar um parâmetro formal em uma das três maneiras a seguir e todos os três methods de declaração produzem resultados semelhantes, porque cada um informa ao compilador que um ponteiro inteiro está indo para ser recebido .

 int func(int arr[], ...){ . . . } int func(int arr[SIZE], ...){ . . . } int func(int* arr, ...){ . . . } 

Então, você está modificando os valores originais.

Obrigado !!!

Arrays em C são convertidos, na maioria dos casos, em um ponteiro para o primeiro elemento do próprio array. E, mais detalhadamente, os arrays passados ​​para funções são sempre convertidos em pointers.

Aqui uma citação da K & R2 :

Quando um nome de matriz é passado para uma function, o que é passado é o local do elemento inicial. Dentro da function chamada, esse argumento é uma variável local e, portanto, um parâmetro de nome de matriz é um ponteiro, ou seja, uma variável que contém um endereço.

Escrevendo:

 void arraytest(int a[]) 

tem o mesmo significado que escrever:

 void arraytest(int *a) 

Então, apesar de você não estar escrevendo isso explicitamente, é como você está passando um ponteiro e então você está modificando os valores no main.

Para mais eu realmente sugiro ler isso .

Além disso, você pode encontrar outras respostas sobre SO aqui

Passando uma multidimensional array como argumento para uma function. Passar um array dim como argumento é mais ou menos trivial. Vamos dar uma olhada no caso mais interessante de passar um array de 2 dim. Em C, você não pode usar um ponteiro para a construção do ponteiro (int **) em vez de um array com 2 colors. Vamos fazer um exemplo:

 void assignZeros(int(*arr)[5], const int rows) { for (int i = 0; i < rows; i++) { for (int j = 0; j < 5; j++) { *(*(arr + i) + j) = 0; // or equivalent assignment arr[i][j] = 0; } } 

Aqui eu especifiquei uma function que toma como primeiro argumento um ponteiro para uma matriz de 5 ints. Eu posso passar como argumento qualquer matriz 2 dim que tenha 5 colunas:

 int arr1[1][5] int arr1[2][5] ... int arr1[20][5] ... 

Você pode chegar a uma idéia para definir uma function mais geral que pode aceitar qualquer array de 2 dim e alterar a assinatura da function da seguinte maneira:

 void assignZeros(int ** arr, const int rows, const int cols) { for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { *(*(arr + i) + j) = 0; } } } 

Este código deve ser compilado, mas você receberá um erro de tempo de execução ao tentar atribuir os valores da mesma maneira que na primeira function. Portanto, em C, uma multidimensional array não é o mesmo que pointers para pointers ... para pointers. Um int (* arr) [5] é um ponteiro para um array de 5 elementos, um int (* arr) [6] é um ponteiro para um array de 6 elementos, e eles são um ponteiro para diferentes tipos!

Bem, como definir argumentos de funções para dimensões superiores? Simples, apenas seguimos o padrão! Hier é a mesma function ajustada para obter uma matriz de 3 dimensões:

 void assignZeros2(int(*arr)[4][5], const int dim1, const int dim2, const int dim3) { for (int i = 0; i < dim1; i++) { for (int j = 0; j < dim2; j++) { for (int k = 0; k < dim3; k++) { *(*(*(arr + i) + j) + k) = 0; // or equivalent assignment arr[i][j][k] = 0; } } } } 

Como você esperaria, pode-se considerar como argumento 3 matrizes que possuem nas segundas dimensões 4 elementos e na terceira dimensão 5 elementos. Qualquer coisa assim seria ok:

 arr[1][4][5] arr[2][4][5] ... arr[10][4][5] ... 

Mas temos que especificar todos os tamanhos de dimensões até o primeiro.

@Bo Persson afirma corretamente em sua grande resposta aqui :

=================================================

Ao passar um array como parâmetro,

 void arraytest(int a[]) 

significa exatamente o mesmo que

 void arraytest(int *a) 

=================================================

No entanto, deixe-me acrescentar também que:

significa exatamente o mesmo que

 void arraytest(int a[0]) 

o que significa exatamente o mesmo que

 void arraytest(int a[1]) 

o que significa exatamente o mesmo que

 void arraytest(int a[2]) 

o que significa exatamente o mesmo que

 void arraytest(int a[1000]) 

etc.

De fato, o valor “size” dentro do parâmetro array aqui é aparentemente apenas para fins estéticos / de auto-documentação, e pode ser qualquer inteiro positivo ( size_t tipo eu acho) que você quer!

Na prática, no entanto, você deve usá-lo para especificar o tamanho mínimo da matriz que espera que a function receba, para que, ao escrever código, seja fácil rastrear e verificar. O padrão MISRA-C-2012 ( comprar / baixar o PDF de 236-pg versão 2012 da norma por £ 15,00 aqui ) vai ao ponto de declarar:

Regra 17.5 O argumento de function correspondente a um parâmetro declarado como tendo um tipo de array deve ter um número apropriado de elementos.

Se um parâmetro for declarado como uma matriz com um tamanho especificado, o argumento correspondente em cada chamada de function deve apontar para um object que tenha pelo menos tantos elementos quanto a matriz.

O uso de um declarator de matriz para um parâmetro de function especifica a interface de function mais claramente do que usando um ponteiro. O número mínimo de elementos esperados pela function é explicitamente declarado, enquanto isso não é possível com um ponteiro. [enfase adicionada]

Em outras palavras, eles recomendam usar o formato de tamanho explícito, embora o padrão C tecnicamente não o imponha – pelo menos ajuda a esclarecer a você como desenvolvedor, e a outros usando o código, qual array de tamanho a function está esperando você passar.