3
respostas

O total é 104768239

Não sei o que errei sempre da um valor absurdo tipo 104768239

#include <stdio.h>
#include <stdlib.h>
#include <locale.h>

void soma(int numeros[10]) {
    int total = 0;
    for(int i = 0; i < 10; i++) {
        total += numeros[i];
    }
    printf("O total é %d", total);
}

int main() {
    setlocale (LC_ALL, "Portuguese");

    int numeros[3];
    numeros[0] = 4;
    numeros[1] = 9;
    numeros[2] = 5;

    soma(numeros);
}   
3 respostas
#include <stdio.h>

int soma(const int* const ptr, int length) {
    int total = 0;
    for (int i = 0; i < length; i++) {
        // a mesma coisa que array[i]. Implicitamente o que está
        // ocorrendo é pegar o valor armazenado em ['endereço base' + i * sizeof(int)]
        total += *(ptr + i);
    }
    return total;
}

int main(int argc, char *argv[]) {
    // quando a inicialização é feita em linha, o compilador é capaz 
    // de determinar  o tamanho do array, e portanto podemos 
    // omiti-lo.
    int array[] = { 0, 1, 2, 3, 4 };

    printf("total: %d\n", soma(array, 5));

    return 0;
}

Teste o código acima. O que você perceberá é que arrays comportam-se de forma análoga a ponteiros, isto é, o nome do array é um alias para o índice 0, e os demais índices são alocados em posições adjacentes de memória, e o acesso se dá por aritmética de ponteiros. Você declarou na função main um array de 3 posições, mas na função soma está lendo 10 posições. Você está acessando posições de memória que não foram inicializadas, e portanto contém lixo (valores residuais aleatórios). Neste caso, em que você está apenas lendo os danos potenciais são menores, contudo, este é um erro grave, que incorre em comportamento indefinido, o que significa que em certas circunstâncias pode fazer o programa acabar prematuramente, em outras pode corromper a memória e gerar resultados inesperados. Altere o limite de iterações do laço para coincidir com o comprimento do array.

#include <stdio.h>

void soma(int numeros[10]) {
    int total = 0;
    for(int i = 0; i < 3; i++) {
        total += numeros[i];
    }
    printf("total: %d", total);
}

int main() {
    int numeros[3];
    numeros[0] = 4;
    numeros[1] = 9;
    numeros[2] = 5;

    soma(numeros);
}   

Acho que entendi o que disse, mas para que serve o argc e o *argv[] que o senhor colocou na função main ?

int main(int argc, char *argv[]) {
    ...
}

Outra coisa porque o senhor usou ptr e lenghth como nomes de variáveis? foi só uma escolha sua ou o senhor queria passar alguma ideia com esses nomes?

insira seu código aqui

Uma última coisa não entendi a seguinte linha const int * const ptr que está entre parênteses da função soma, poderia me explicar?

  1. argc e argv são os argumentos de linha de comando, que lhe permitem passar valores ao seu programa no momento da inicialização. Nesse caso específico não tem qualquer utilidade.
  2. O código acabou ficando parte em português e parte em inglês, pois foi baseado em uma versão refatorada do seu código, no entanto, em geral, meus códigos são todos escritos em inglês; arquivos, tipos, funções, variáveis, comentários e documentação. A escolha dos nomes é arbitrária, mas foi feita seguindo convenções. ptr é uma abreviação para ponteiro, e length significa comprimento. Ou seja, o primeiro parâmetro passa o endereço base, o segundo o comprimento do array.
  3. Quanto a const int* const ptr, é um pouco mais complicado. Basicamente, o endereço apontado não pode ser modificado e os valores contidos nos blocos de memória são imutáveis. O objetivo desta declaração é deixar explícito tratar-se de uma função pura, isto é, que não gera side-effects nos parâmetros passados, e produz um valor de retorno com base em algum processamento sobre estes dados.
  4. Repare que a mesma função que eu havia definido anteriormente, pode ser reescrita desta forma. A intenção anterior era mostrar a analogia entre o acesso a índices de um vetor e aritmética de ponteiros. No entanto, esta forma é muito mais legível.
    int sum(const int* const ptr, const int length) {
        int acc = 0;
        for (int i = 0; i < length; i++)
            acc += ptr[i];
        return acc;
    }

  5. Neste exemplo, podemos observar um funcionamento mais complexo:
    // iterator.h
    
    #ifndef ITERATOR_H_
    #define ITERATOR_H_
    
    #include <stdarg.h>
    #include <stdbool.h>
    
    typedef struct iterator* iterator_t;
    
    iterator_t createIterator(int, void*, void*(*const)(iterator_t, void*, const int), int(*const)(iterator_t, void*));
    
    bool hasNextIterator(iterator_t);
    
    int getIterator(iterator_t);
    
    void stepUpIterator(iterator_t);
    
    void deleteIterator(iterator_t*);
    
    #endif
    
    // iterator.c
    
    #include <stdlib.h>
    #include <string.h>
    
    #include "iterator.h"
    
    struct iterator {
        int index;
        const int max;
        void *ptr;
    
        void *(*const dereference)(iterator_t, void *, const int);
    
        int (*const get)(iterator_t, void *);
    };
    
    static const int SIZE = sizeof(struct iterator);
    
    iterator_t createIterator(
            int length,
            void *ptr,
            void *(*const dereference)(iterator_t, void *, const int),
            int(*const get)(iterator_t, void *)
    ) {
        const struct iterator ITERATOR = {0, length, ptr, dereference, get};
    
        iterator_t it = (iterator_t) malloc(SIZE);
        if (it != NULL)
            memmove(it, &ITERATOR, SIZE);
        return it;
    }
    
    bool hasNextIterator(iterator_t it) {
        bool guard = it->index < it->max;
        if (!guard)
            it->index = 0;
        return guard;
    }
    
    int getIterator(iterator_t it) {
        return it->get(it, it->dereference(it, it->ptr, it->index));
    }
    
    void stepUpIterator(iterator_t it) {
        it->index++;
    }
    
    void deleteIterator(iterator_t *it) {
        free(*it);
    }
    // main.c
    
    #include <time.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    #include "iterator.h"
    
    void* defaultDereference(iterator_t it, void *ptr, int index) {
        return NULL;
    }
    
    int randomGeneratedNext(iterator_t it, void *ptr) {
        return abs(rand()) % 100 + 1;
    }
    
    void* commandLineDereference(iterator_t it, void *ptr, int index) {
        return ((char**)ptr)[index + 1];
    }
    
    int commandLineNext(iterator_t it, void *ptr) {
        return atoi((char*)ptr);
    }
    
    int sum(iterator_t it) {
        int acc = 0;
        for (; hasNextIterator(it); stepUpIterator(it))
            acc += getIterator(it);
        return acc;
    }
    
    int main(int argc, char **argv) {
        srand(time(NULL));
    
        iterator_t it = (argc > 1) 
            ? createIterator(argc - 1, argv, commandLineDereference, commandLineNext)
            : createIterator(10, NULL, defaultDereference, randomGeneratedNext);
    
        printf("sum = %d\n", sum(it));
    
        deleteIterator(&it);
    
        return 0;
    }
    #Makefile
    CC=clang
    CFLAGS=-Winline -Wall -Werror -O3 -std=c11
    SRC=$(wildcard *.c)
    OBJ=$(SRC:.c=.o)
    ASM=$(SRC:.c=.s)
    EXE=prog
    
    all: $(EXE)
    
    $(EXE): $(OBJ)
        $(CC) $^ -o $@ $(CFLAGS)
    
    %.s: %.c
        $(CC) -S -o $@ -c $< $(CFLAGS)
    
    %.o: %.c
        $(CC) -o $@ -c $< $(CFLAGS)
    
    .PHONY: clean cleanAll
    
    clean:
        @rm -Rfv *.s *.o
    
    cleanAll: clean
        @rm prog

    Para saber como usar um arquivo Makefile, você pode ler aqui ou aqui. Segue a documentação em pdf.