Solucionado (ver solução)
Solucionado
(ver solução)
1
resposta

Eu ainda não entendi porque preciso determinar o tamanho da Array. A variável deve ficar apenas no escopo da soma? Ou deve fazer um Ponteiro pra ele? Estou perdido :(

#include <stdio.h>

int soma(int nums[3], int* tamanho) {
    int total = 0;
    for(int i = 0; i < *tamanho; i++){
        total += nums[i];
        printf("%d\n",nums);

    }
    return total;
}

int main(){
    int tamanho;
    int nums[3];
    nums[0] = 10;
    nums[1] = 20;
    nums[2] = 30;

    int total;
    total = soma(nums, &tamanho);

}
1 resposta
solução!

Peguei o teu código e dei uma alterada nele para que ele funcione como deve. Abaixo, tentarei explicar como tudo funciona.

#include <stdio.h>

#define TAMANHO 3

int soma(int nums[], int tamanho) {
    int total = 0;
    for (int i = 0; i < tamanho; i++) {
        total += nums[i];
        printf("%d\n", nums[i]);
    }
    return total;
}

int main(int argc, char *argv[]) {
    // Use uma macro com o valor do tamanho, dessa forma, se precisar
    //  mudar o tamanho, só muda em um lugar, na definição da macro
    int nums[TAMANHO];

    // Se o  array for grande, e a lógica de inicialização simples, 
    // inicialize com um loop. Veja mais abaixo a forma ideal
    // de definir arrays de tamanho pequeno
    for (int i = 0; i < TAMANHO; i++)
        nums[i] = (i + 1) * 10;

    int total = soma(nums, TAMANHO);
}

Em C, arrays são ponteiros implíticos, ou seja, o nome refere-se à posição de memória do primeiro elemento, o índice 0. Como o compilador sabe o tamanho que cada tipo de dado ocupa em memória, e todos os elementos do array estão em posições adjacentes de memória, ele percorre o array por meio de aritmética de ponteiros. Segue um exemplo de código que demonstra isso:

#include <stdio.h>

#define TAMANHO 10

int main(int argc, char *argv[]) {
    int array[TAMANHO];

    int *ptr = array;

    // Repare que estou inicializando o array por meio de ptr
    for (int i = 0; i < TAMANHO; i++)
        *(ptr + i) = i*i;

    // Verifique que funciona
    for (int i = 0; i < TAMANHO; i++)
        printf("%d, ", array[i]);

    return 0;
}

Aqui vem uma tecnicalidade de arquitetura de computadores!

Um programa é composto de segmentos de memória distintos, sendo eles, do endereço mais alto para o mais baixo:

  1. Pilha (Stack): onde parâmetros de funções são alocados
  2. Heap: de onde se obtém memória dinâmicamente por meio de malloc ou calloc
  3. Dados: segmento estático de dados, ou seja, cujo tipo, dimensão e escopo são conhecidos em tempo de compilação
  4. Texto: instruções que compõem o programa (sim, instruções possuem endereço!)

Em C, arrays são instanciados estaticamente --- leia-se tempo de compilação --- portanto residem no segmento de dados. Por este motivo, o compilador tem de saber, além do tipo, o tamanho do array. Uma das formas abaixo deve ser utilizada para declarar um array:

// O tamanho é definido implicitamente pelo compilador, e 
// os elementos do array inicializados
int array[] = { 10, 20, 30 };

// O tamanho é definido explicitamente, e os elementos não são inicializados
int array[3];

// Uma forma elegante do padrão C99 para inicializar todos os
// elementos do array com valor nulo. Válido também para estruturas
int array[3] = { 0 };

Em C, por padrão, parâmetros de funções são sempre passados por valor, ou seja, é criada uma cópia na pilha para que a função use. Consequentemente, alterações realizadas dentro das funções não geram side-effects. Repare no código abaixo, o valor de i não se alterou após a execução de func.

#include <stdio.h>

void func(int arg) {
    arg += 10;
}

int main(int argc, char *argv[]) {
    int i = 5;

    printf("%d\n", i);
    func(i);
    printf("%d\n", i);    

    return 0;
}

Nem sempre, entretanto, esse é o comportamento desejado pelo programador. Seja por eficiência, pois copiar estruturas grandes é custoso, seja por conveniência, pois deseja-se que as alterações nos dados passados às funções sejam efetivamente guardadas. Nessas situações, desejamos realizar uma passagem por referência. Repare no código abaixo:

#include <stdio.h>

void func(int *arg) {
    *arg += 10;
}

int main(int argc, char *argv[]) {
    int i = 5;

    printf("%d\n", i);
    func(&i);
    printf("%d\n", i);    

    return 0;
}

Esse --- juntamente às callbacks, alocação dinâmica de memória, criação de TADs e programação genérica --- é o uso de ponteiros na linguagem C! Para qualquer outra finalidade, uma vez que não seja estritamente necessário, evite usar ponteiros, seu uso dificulta a legibilidade do programa conforme o nível de indireção aumenta, e erros relacionados a ponteiros costumam ser difícies de encontrar.

Adendo:

Atenção! Lembra que arrays são ponteiros implícitos? Pois bem, isso significa que seu conteúdo é sempre passado por referência. Portanto, alterações realizadas dentro de uma função chamada alteram o array na função chamadora.