Cara fantástica a aula do Wagber Rambo, literalmente vestindo a camisa do C! Lembrando que já faz mais de 20 anos que falam em acabar com a linguagem C, mas quando é necessário performance com portabilidade todo mundo corre para utilizar a linguagem C, são inúmeras aplicações escritas em C/C++ do sistema operacional que você utiliza passando por navegadores até o back end da pagina de busca do google é C! O Android do seu celular é escrito em C o núcleo do iOS do iphone é C! Parabéns Wagner! Bora, bora, bora!
sim mano, mesmo Rust sendo tão rápida quanto C acho muito difícil tomar o lugar disso, principalmente sistemas em que "código não seguro" são necessário.
@@canalwrkits C e C++ é a base de tudo, eles podem tentar destruir, nunca vão conseguir substituir ambos... C é poderoso... e direto (um grande obrigado ao Sr Dennis Ritchie e Thompson) C++ como diria o nosso saudoso Bjarne, é o C com classes. Não importa o quanto o mercado tente mudar isso... C e C++ são a base de tudo. Eu recomendo fortemente inclusive, eu todo mundo que quer entrar na programação, dê uma olhada, mesmo que rápida, é basicamente supreendente o que se pode aprender e ver como evoluiu.
Boa, poderia fazer um complemento de comparações usando assembly com as funções FSR e INDF, escrito na "unha" e ver se tbm da diferença ou não usar diretamente o assembly para projetos embarcados que exige maxima eficiência de aproveitamento dos ciclos de maquina...
na verdade eu comparei aqui o assembly das duas funçoes, são iguais (clang -O1 -nostdlib) como você citou em um comentário sobre o compilador ser proprietário, eu imagino que seja ele quem está gerando essa diferença. nao consigo imaginar nenhum jeito mais rápido de reescrever essa função, ainda assim, bom vídeo!
Ele compilou sem otimizações no vídeo. Ligando otimização, o gcc vai otimizar e vai ficar igual. Note que se for sem otimização, com ponteiros ainda daria pra calcular fora do loop o endereço do final do array, e usar comparação do ponteiro como condição do loop, evitando ter que incrementar a variável de controle do loop (i).
@@Prescott2400-my6di Entendo o que você quis dizer, e é incrível como esses CIs gerenciam suas memórias, isso é fascinante, mas eu comparei somente as duas funções, sem a main, acredito que depois das otimizações, como você mesmo disse, esse gerenciamento do array faça diferença. Sendo assim a possibilidade do compilador que eu mencionei não faz sentido.
@@Prescott2400-my6diParabéns pelo complemento da aula, vim aqui perguntar ou sugerir exatamente isso, o porque fica mais lento. Obrigado pela explicação.
@@naldin007 alguns dias atrás eu pedi pra produção reproduzir um .hex de um micro que peguei como base de um projeto meu, aquele .hex demorava 1,30s para fazer a gravação. O diaque gerei .hex pelo o compilar e direcionado o endereço de memoria do inicio ao fim, o processo da produção foi 10s para 3s. Acho que os ponteiors de memoria é valido SIM. isso me aconteceu com STM32
Muito bom! Ótima explicação! E o seu método para visualizar o tempo de execução foi simples e eficaz! Na minha opinião, ponteiros são muito úteis na otimização de programas, mas só depois que você domina o uso. Tem que saber exatamente o que está fazendo. Tanto que algumas linguagens aboliram o uso explícito de ponteiros, como Java, C# e Python, porque como o ponteiro literalmente aponta para o endereço de memória de outra variável para ler/escrever seu conteúdo, se por um erro do programa o ponteiro apontar para o endereço errado, vai mexer onde não deve resultando em problemas. Em programas Windows isso geralmente resulta na tela azul (BSOD), trava o computador e a única solução é reiniciar o Windows. Em microcontroladores, um erro de violação de acesso de memória por uso de ponteiros pode causar falhas aparentemente aleatórias e travamentos inesperados, visto que (geralmente) não há sistema operacional para gerenciar os recursos da máquina. O uso do watchdog timer é um aliado nesses casos.
Depende do nível de otimização do compilador tb. Pegue o assembly gerado e aí vai perceber que no caso da versão com uso do array direto, provavelmente o compilador está usando a stack implicitamente para referenciar variavel array com o índice. Resumindo, cada instrução importa em microcontroladores e demais arquiteturas com baixo poder de processamento
Grande Aula !! Dá pra otimizar ainda mais esta operação: int sum_array_ptr(int * ptr, int size) { int sum = 0; while ( size ) { sum += *ptr++; size--; } return sum; }
Bela explicação professor! Destaco o cuidado na estrutura do código ao uso da palavra reservada 'register', são estes 'pequenos' detalhes que acabam fazendo uma boa diferença em um projeto extenso. Sucesso querido Wagner, obrigado pelo vídeo :)
Concordo, ponteiros são excelentes, quando se deseja agilidade, inclusive. Vale lembrar que utilizar variáveis como bits de sinalização, também aumenta a eficiência.
Cara... você continua fora da curva mesmo depois de 10 anos. Você bagunçou a minha cabeça kkkkk. Eu confeso que eu preciso revisar isso ai ate eu entender. O principio do ponteiro em grande escala é a salvação, eu vou tentar aplicar em meus projetos existente. Show demais!!!!
Eu gostei, eu ja sou um fã de ambas C e C++, como diria o Sr Bjourne... C com classes... são coisas assim que mostram o potencial da linguagem em si (eu uso ambas, e gosto de ambas). Muito bom, infelizmente vivemos em um mundo onde empresas e pessoas prezam pelo lucro e praticidade, e não pela eficiência (me corrijam se eu estiver errado). Muito bom.
Perfeitamente, o Bjourne originalmente batizou C++ como "C com Classe", bem lembrado hehe. Acredito que consigamos buscar lucro e praticidade ainda nos dias de hoje com C/C++;
@@canalwrkits Sim, exatamente, infelizmente o grande problema é que as empresas (não são todas, claro, mas infelizmente a maior parte do mercado é assim) Exigem Python, Javascript, Java, C#, nada contra essas ferramentas e linguagens, mas as empresas nos dias de hoje, querem agilidade e praticidade, então... Como C e C++ é para programadores raíz, e o mercado de certa forma é nutella, não quer perder tempo e ja partem para algo mais prático para produzir... Mas esse prático, sacrifica a base para o entendimento das funções, e demais assuntos como Otimização de código e tudo mais. Coisa que o C e C++ aborda e ensina muito bem. Eu até comentei isso com um outro colega aqui, o Judson Santiago (Professor de C++), o foco dele é Interfaces gráficas e jogos. C e C++ basicamente são a base de tudo o que temos hoje, programação orientada a objetos, programação procedural, paradigmas, etc... mas a turma hoje em dia, não sabem disso, é complicado.
Esse ganho de performance aparentemente pequeno faz muita diferença em softwares maiores. Sou fã da Línguagem C. Eu estou acostumado com linguagens de programação interpretadas, mas também estou investindo tempo na linguagem C. Eu sou fascinado por eficiência, e gosto da ideia de trabalhar mais próximo do Hardware, diferente do que acontece com Python, Java e Kotlin (que é a linguagem que eu estudo em paralelo a linguagem C atualmente, para apps Android). Ótimo video.
Bom vídeo mas fiquei curioso para saber como o fato de ter um pulo condicional (else) no código afetou os resultados. Seria legal ver o mesmo exemplo mas usando dessa vez duas versões do código diferentes
Obrigado Pedro! Se você está se referindo ao if/else do começo, simplesmente fazemos a seleção da função utilizada. if verdadeiro, usamos a função sem ponteiros, if falsa processa o else e usamos a versão com ponteiros.
Quais flags de otimização para o compilador foram usadas para gerar o binário enviado ao microcontrolador? Qual a versão do GCC usado para o microcontrolador?
O MikroC é um compilador proprietário desenvolvido pela MikroElektronika especificamente para programação em linguagem C para microcontroladores PIC da Microchip. O MikroC Pro for PIC possui sua própria ferramenta de compilação e não depende do GCC para gerar código executável para os dispositivos PIC.
Bem legal! Muito legal ter demonstrado no osciloscópio. Mas corrija-me se estiver equivocado pois sou novato em C. Se houver algum erro na condição de fim do looping, você pode acabar acessando o valor de outra variável (ex: suponhamos que você calculou o término do array equivocadamente, errado por 1 a mais). E se for uma função que altere valores (não apenas leia) isso pode ser ainda mais arriscado Estou correto em pensar que ao mesmo tempo poderoso e otimizador, precisa ter cuidado com o uso de ponteiros?
Existe a linguagem C e existe o resto... Para microcontroladores, não há nada melhor que os ponteiros, pois na maioria das arquiteturas os registradores dos periféricos são mapeados em memória. Para acessar o endereço explícito, nada melhor do que um ponteiro. Além disso, como os registradores de um dado periférico costumam estar em endereços contíguos, podemos configurar múltiplos registradores apenas avançando o ponteiro.
Mano tras mais conteúdo disso. Eu vejo gente falando que ponteiros não tem tanta necessidade de aprender. Pessoalmente venho criando mais intimidade com c e c++. Eu vi como alguns codigos e jogos feito praticamente com isso são leve e poderosos. Engines com graficos surreais gastando alguns mb de ram e gpu trabalhando praticamente com folga. Claro que é um desafio imerso fazer um jogo inteiro. Claro. To visando aprender para contribuír com projetos opensource voltado a pesquisas científicas e ferramentas de uso geral. Krita por exemplo
Bom vídeo. Porém este exemplo é específico (acesso sequencial aos dados), o resultado é distinto pois se está comparado um acesso sequencial (com ponteiros) e um acesso aleatório (com variáveis). Lembrando que uma das principais características da "liguagem C" é o tratamento interno das variáveis como ponteiros. Uma comparação correta seria comparar uma rotina de acesso aleatório utilizando ponteiros e variáveis (duas abordagens sobre a mesma questão buscada).
Estranho, pois em C uma função que recebe um parâmetro int array[] é a mesma coisa que uma que recebe um argumento int *array. Essa diferença deve ser por causa do compilador, pois as duas formas são iguais.
agora tem que fazer um speedrun de quantos segundos leva até conseguir colocar uma falha de segurança no sistema sem o intuito de causar falha de segurança.
Olá Prof. Wagner, tudo bem? Grato pelo vídeo e espero que essa situação no RS melhore o mais rápido possível. Também sou professor de programação em linguagem C e sempre considerei "array[i]" equivalente a "*(array + i)", mesmo sendo os códigos de máquina gerados ligeiramente diferentes. Nesse vídeo, fiquei curioso se, na instrução "for" da função "sum_array_ptr", "sum += *(ptr + i);" teria o mesmo desempenho que "sum += *ptr; ptr++;" em microcontroladores. Outra dúvida: Haveria ganho ao substituir a instrução "register int i;" por "register int *ptr = array;" conforme o código seguinte? int sum_array_ptr(int *array, int size) { int sum = 0; register int *ptr = array; int *ptr_final = ptr + size; while (ptr < ptr_final) { sum += *ptr; ptr++; } return sum; } Abs.
sum += *(ptr + i);: Nesta instrução, você está acessando o valor no endereço apontado por ptr + i, onde i é um contador que aumenta a cada iteração do loop. Isso significa que, a cada iteração, o processador precisa calcular o endereço que está i posições à frente de ptr, o que pode exigir operações adicionais de adição e desreferenciação de ponteiro. Essas operações extras podem afetar o desempenho em microcontroladores, especialmente se a otimização do compilador não conseguir simplificar essas operações. sum += *ptr; ptr++;: Nesta instrução, você simplesmente acessa o valor apontado por ptr e, em seguida, incrementa o ponteiro ptr. Esta abordagem pode ser mais eficiente em microcontroladores, pois não envolve cálculos adicionais de endereço a cada iteração. Apenas a desreferenciação do ponteiro e o incremento do ponteiro são necessários. Na instrução sum += *ptr; ptr++; o desempenho é ligeiramente melhor, pois simplesmente acessamos o valor apontado por ptr e, em seguida, incrementa o ponteiro ptr. Em sum += *(ptr + i); você está acessando o valor no endereço apontado por ptr + i, onde i é um contador que aumenta a cada iteração do loop. Isso significa que, a cada iteração, o processador precisa calcular o endereço que está i posições à frente de ptr, o que pode exigir operações adicionais de adição. Em sua outra dúvida, não há ganho em substituir register int i; por register int *ptr = array; no seu código. abs!
Esse vídeo me fez passar a última hora estudando ponteiros em C. No meio do meu estudo me deparei com a seguinte afirmação: "A indexação array[i] é traduzida pelo compilador em aritmética de ponteiros nos bastidores." Baseado nessa informação e no seus 2 códigos, um percorrendo o array por indexação e outro com ponteiros, o compilador não traduziria ambos para as mesmas instruções? Você respondeu isso no vídeo, mostrando que com ponteiros o processamento é mais rápido, e foi ai que minha cabeça explodiu, POR QUÊ é mais rápido!? 🤣
Sua constatação foi excelente Gustavo e meu objetivo com o vídeo foi atingido. Fazer a galera estudar mais os ponteiros. Vou esclarecer a questão para você. Compiladores modernos são muito eficientes e podem otimizar muitas dessas diferenças. No entanto, a forma com ponteiros é muitas vezes mais simples de otimizar pelo compilador, já que as operações são mais diretas e há menos cálculos repetidos. O acesso sequencial direto que o código com ponteiros provê tende a ser melhor preditível do que os cálculos de endereços repetidos. O que ocorre é que ao usar um compilador bastante eficiente em otimizações, geralmente temos a otimização correta em ambos os casos, como você observou. Na prática, apliquei os testes em MikroC, que apresenta um compilador proprietário dedicado a arquiteturas reduzidas, que são os microcontroladores, o que não gerou tal otimização.
Muito obrigado Anderson! Recomendo fortemente ambas as linguagens. Para começar, Linguagem C. Temos o curso Definitivo, é o mais completo do mercado: go.hotmart.com/N48026554Y Bons estudos!
Ponteiros são ótimos mas existe ressalvas, Ponteiros deixam o código mais complexo de leitura e manutenção. Ponteiros não possui proteção para acesso a uma memória nula isso pode quebrar o código. Ponteiro podem apontar para endereços de memórias livres(endereços de memória que não foram alocadas) causando quebra do código. Ponteiros não são mapeados, ou seja, você pode perfeitamente acessar um endereço de memoria que nao existe e isso quebra o código em tempo de execução. Ponteiros a maior parte dos erros dos ponteiros são descobertos apenas em tempo de execução. Ponteiros que alocam memória ai que a coisa pode ficar feia mesmo. Tenho estudado sobre hackeamento de sistemas embarcados, e softwares com ponteiros são mais fáceis de ler o assembler e hackear. No meu modo de programar utilizo ponteiro apenas em situações de eficiência de busca e calculo, no processo normal do codigo não utilizo, mesclar as dois paradigmas na minha visão é o ideal, cada qual na sua finalidade.
Uma pergunta, pq usar "sizeof(arr) / sizeof(arr[0]) ?? Nao seria mais facil usar so o sizeof(arr) ou sizeof(arr) -1? Ou muda alguma coisa nesse contexto?
Em C, sizeof() de um array retorna o total de bytes dele. Daí você tem que dividir pelo total de bytes do tipo de variável que ele armazena para obter o total de elementos do array. Exemplo: sizeof(arr)/sizeof(arr[0]) Ou, nesse caso: sizeof(arr)/sizeof(int)
Acesse o link: go.hotmart.com/N48026554Y e faça a aquisição. Ao confirmar o pagamento, você receberá o link de acesso ao curso por email. Então é só acompanhar as aulas. O acesso é vitalício. Aguardo você no curso!
@@canalwrkits Creio que sim, mudança na administração pública e querem pagar de modernões(Rust é a linguagem "queer", é cada uma viu), muita besteira num documento só.
Show de bola Wagner como vc esta irmão força para vc e os irmãos aí do sul do país
Valeu meu amigo! Tempos bem difíceis.
É cerca de 17% mais rápido, fazendo exatamente a mesma coisa. Sem dúvidas que é um baita aumento de eficiência.
Cara fantástica a aula do Wagber Rambo, literalmente vestindo a camisa do C! Lembrando que já faz mais de 20 anos que falam em acabar com a linguagem C, mas quando é necessário performance com portabilidade todo mundo corre para utilizar a linguagem C, são inúmeras aplicações escritas em C/C++ do sistema operacional que você utiliza passando por navegadores até o back end da pagina de busca do google é C! O Android do seu celular é escrito em C o núcleo do iOS do iphone é C! Parabéns Wagner! Bora, bora, bora!
Exatamente meu amigo. O C é indestrutível :)
A base de várias linguagens interpretadas e compiladores é o C kkkkkk. Impossível acabar com ele
sim mano, mesmo Rust sendo tão rápida quanto C acho muito difícil tomar o lugar disso, principalmente sistemas em que "código não seguro" são necessário.
isso mesmo
@@canalwrkits C e C++ é a base de tudo, eles podem tentar destruir, nunca vão conseguir substituir ambos...
C é poderoso... e direto (um grande obrigado ao Sr Dennis Ritchie e Thompson)
C++ como diria o nosso saudoso Bjarne, é o C com classes.
Não importa o quanto o mercado tente mudar isso... C e C++ são a base de tudo.
Eu recomendo fortemente inclusive, eu todo mundo que quer entrar na programação, dê uma olhada, mesmo que rápida, é basicamente supreendente o que se pode aprender e ver como evoluiu.
Excelente demonstração. Gostei do método do teste! ... Muita força para todos daí para voltar tudo aos eixos novamente!!!
Boa, poderia fazer um complemento de comparações usando assembly com as funções FSR e INDF, escrito na "unha" e ver se tbm da diferença ou não usar diretamente o assembly para projetos embarcados que exige maxima eficiência de aproveitamento dos ciclos de maquina...
Sugestão anotada, valeu!
Sempre tive dificuldades para entender a importancia e o uso dos ponteiros, acabou de me esclarecer. Muito obrigado
Mais uma super aula meu amigo! Dica valiosa para todos que curtem Linguagem C! Que venham mais aulas como esta! Sempre acompanhando! Forte abraço!!!
Muito obrigado meu amigo! Sempre que possível trarei dicas assim, forte abraço!!!
na verdade eu comparei aqui o assembly das duas funçoes, são iguais (clang -O1 -nostdlib)
como você citou em um comentário sobre o compilador ser proprietário, eu imagino que seja ele quem está gerando essa diferença.
nao consigo imaginar nenhum jeito mais rápido de reescrever essa função, ainda assim, bom vídeo!
Ele compilou sem otimizações no vídeo. Ligando otimização, o gcc vai otimizar e vai ficar igual. Note que se for sem otimização, com ponteiros ainda daria pra calcular fora do loop o endereço do final do array, e usar comparação do ponteiro como condição do loop, evitando ter que incrementar a variável de controle do loop (i).
@@Prescott2400-my6di Entendo o que você quis dizer, e é incrível como esses CIs gerenciam suas memórias, isso é fascinante, mas eu comparei somente as duas funções, sem a main, acredito que depois das otimizações, como você mesmo disse, esse gerenciamento do array faça diferença. Sendo assim a possibilidade do compilador que eu mencionei não faz sentido.
@@Prescott2400-my6dinão faz sentido,, na versão com array o compilador deveria simplesmente passar o ponteiro também, qualquer compilador faria isso.
@@Prescott2400-my6diParabéns pelo complemento da aula, vim aqui perguntar ou sugerir exatamente isso, o porque fica mais lento. Obrigado pela explicação.
@@naldin007 alguns dias atrás eu pedi pra produção reproduzir um .hex de um micro que peguei como base de um projeto meu, aquele .hex demorava 1,30s para fazer a gravação. O diaque gerei .hex pelo o compilar e direcionado o endereço de memoria do inicio ao fim, o processo da produção foi 10s para 3s. Acho que os ponteiors de memoria é valido SIM. isso me aconteceu com STM32
Impressionante! Eu achava que não tinha diferença já o índice especifico acessa diretamente o valor como um ponteiro faz, muito bom saber disso.
Muito bom! Ótima explicação! E o seu método para visualizar o tempo de execução foi simples e eficaz! Na minha opinião, ponteiros são muito úteis na otimização de programas, mas só depois que você domina o uso. Tem que saber exatamente o que está fazendo. Tanto que algumas linguagens aboliram o uso explícito de ponteiros, como Java, C# e Python, porque como o ponteiro literalmente aponta para o endereço de memória de outra variável para ler/escrever seu conteúdo, se por um erro do programa o ponteiro apontar para o endereço errado, vai mexer onde não deve resultando em problemas. Em programas Windows isso geralmente resulta na tela azul (BSOD), trava o computador e a única solução é reiniciar o Windows. Em microcontroladores, um erro de violação de acesso de memória por uso de ponteiros pode causar falhas aparentemente aleatórias e travamentos inesperados, visto que (geralmente) não há sistema operacional para gerenciar os recursos da máquina. O uso do watchdog timer é um aliado nesses casos.
Obrigado Fernando! Muito bem observado, o uso dos ponteiros deve ser consciente e com cautela por estas razões.
gostei.... é interressante demais o assunto, principalmente para os amantes de arduino UNO/derivados. Isso pode salvar muitos projetos existente
Muito bom. Fiquei curioso o que muda na parte código de máquina.
Vou fazer o teste e olhar o binário gerado.
Conta para gente!
amo seu canal, muito obrigado por continuar postando conteúdo de qualidade ♥
Parabéns pelo vídeo. Poderia fazer um vídeo sobre como contornar problemas com EMI. Abraços!
Muito obrigado! Sugestão anotada!
Depende do nível de otimização do compilador tb.
Pegue o assembly gerado e aí vai perceber que no caso da versão com uso do array direto, provavelmente o compilador está usando a stack implicitamente para referenciar variavel array com o índice.
Resumindo, cada instrução importa em microcontroladores e demais arquiteturas com baixo poder de processamento
Grande Aula !! Dá pra otimizar ainda mais esta operação:
int sum_array_ptr(int * ptr, int size)
{
int sum = 0;
while ( size ) {
sum += *ptr++;
size--;
}
return sum;
}
Show de bola!
Bela explicação professor! Destaco o cuidado na estrutura do código ao uso da palavra reservada 'register', são estes 'pequenos' detalhes que acabam fazendo uma boa diferença em um projeto extenso. Sucesso querido Wagner, obrigado pelo vídeo :)
Muito obrigado Gercino! Sucesso!
Concordo, ponteiros são excelentes, quando se deseja agilidade, inclusive. Vale lembrar que utilizar variáveis como bits de sinalização, também aumenta a eficiência.
Cara... você continua fora da curva mesmo depois de 10 anos. Você bagunçou a minha cabeça kkkkk. Eu confeso que eu preciso revisar isso ai ate eu entender. O principio do ponteiro em grande escala é a salvação, eu vou tentar aplicar em meus projetos existente. Show demais!!!!
Valeu Rafael! Acompanhe sempre! :)
Muito bem explicando 👏
Eu gostei, eu ja sou um fã de ambas C e C++, como diria o Sr Bjourne... C com classes...
são coisas assim que mostram o potencial da linguagem em si (eu uso ambas, e gosto de ambas).
Muito bom, infelizmente vivemos em um mundo onde empresas e pessoas prezam pelo lucro e praticidade, e não pela eficiência (me corrijam se eu estiver errado).
Muito bom.
Perfeitamente, o Bjourne originalmente batizou C++ como "C com Classe", bem lembrado hehe. Acredito que consigamos buscar lucro e praticidade ainda nos dias de hoje com C/C++;
@@canalwrkits Sim, exatamente, infelizmente o grande problema é que as empresas (não são todas, claro, mas infelizmente a maior parte do mercado é assim)
Exigem Python, Javascript, Java, C#, nada contra essas ferramentas e linguagens, mas as empresas nos dias de hoje, querem agilidade e praticidade, então... Como C e C++ é para programadores raíz, e o mercado de certa forma é nutella, não quer perder tempo e ja partem para algo mais prático para produzir...
Mas esse prático, sacrifica a base para o entendimento das funções, e demais assuntos como Otimização de código e tudo mais.
Coisa que o C e C++ aborda e ensina muito bem.
Eu até comentei isso com um outro colega aqui, o Judson Santiago (Professor de C++), o foco dele é Interfaces gráficas e jogos.
C e C++ basicamente são a base de tudo o que temos hoje, programação orientada a objetos, programação procedural, paradigmas, etc... mas a turma hoje em dia, não sabem disso, é complicado.
Excelente vídeo, mestre!
Esse ganho de performance aparentemente pequeno faz muita diferença em softwares maiores.
Sou fã da Línguagem C.
Eu estou acostumado com linguagens de programação interpretadas, mas também estou investindo tempo na linguagem C. Eu sou fascinado por eficiência, e gosto da ideia de trabalhar mais próximo do Hardware, diferente do que acontece com Python, Java e Kotlin (que é a linguagem que eu estudo em paralelo a linguagem C atualmente, para apps Android).
Ótimo video.
Valeu Emerson! Não sei se já fez, mas considere nosso curso Definitivo de C, vai aprender muito e de forma rápida: go.hotmart.com/N48026554Y
Bom vídeo mas fiquei curioso para saber como o fato de ter um pulo condicional (else) no código afetou os resultados. Seria legal ver o mesmo exemplo mas usando dessa vez duas versões do código diferentes
Obrigado Pedro! Se você está se referindo ao if/else do começo, simplesmente fazemos a seleção da função utilizada. if verdadeiro, usamos a função sem ponteiros, if falsa processa o else e usamos a versão com ponteiros.
Que aula bacana. Obrigado.
Quais flags de otimização para o compilador foram usadas para gerar o binário enviado ao microcontrolador? Qual a versão do GCC usado para o microcontrolador?
O MikroC é um compilador proprietário desenvolvido pela MikroElektronika especificamente para programação em linguagem C para microcontroladores PIC da Microchip. O MikroC Pro for PIC possui sua própria ferramenta de compilação e não depende do GCC para gerar código executável para os dispositivos PIC.
@@canalwrkits obrigado 😄
Excelente review!
Comprei o curso esp 32....❤
Excelente! Vai gostar bastante, bons estudos e sucesso!
Que aula legal
Bem legal! Muito legal ter demonstrado no osciloscópio. Mas corrija-me se estiver equivocado pois sou novato em C.
Se houver algum erro na condição de fim do looping, você pode acabar acessando o valor de outra variável (ex: suponhamos que você calculou o término do array equivocadamente, errado por 1 a mais). E se for uma função que altere valores (não apenas leia) isso pode ser ainda mais arriscado
Estou correto em pensar que ao mesmo tempo poderoso e otimizador, precisa ter cuidado com o uso de ponteiros?
Isso mesmo Vitor. Devemos usar ponteiros com cautela.
cara como está aí o seu estado tô preocupado com vocês.
Está terrível.
Existe a linguagem C e existe o resto... Para microcontroladores, não há nada melhor que os ponteiros, pois na maioria das arquiteturas os registradores dos periféricos são mapeados em memória. Para acessar o endereço explícito, nada melhor do que um ponteiro. Além disso, como os registradores de um dado periférico costumam estar em endereços contíguos, podemos configurar múltiplos registradores apenas avançando o ponteiro.
Mano tras mais conteúdo disso. Eu vejo gente falando que ponteiros não tem tanta necessidade de aprender. Pessoalmente venho criando mais intimidade com c e c++. Eu vi como alguns codigos e jogos feito praticamente com isso são leve e poderosos. Engines com graficos surreais gastando alguns mb de ram e gpu trabalhando praticamente com folga. Claro que é um desafio imerso fazer um jogo inteiro. Claro. To visando aprender para contribuír com projetos opensource voltado a pesquisas científicas e ferramentas de uso geral. Krita por exemplo
Obrigado! Traremos sim. Recomendo bastante nossos cursos de C/C++ para você que quer se profissionalizar. Dê uma olhada em wrkits.com.br/cursos
Pq precisa primeiro gerar um assembly? Não pode compilar direto com o gcc e executar?
Pode também Gustavo. Eu quis demonstrar como gera o Assembly para aqueles que quiserem também analisar o código em baixo nível.
Bom vídeo. Porém este exemplo é específico (acesso sequencial aos dados), o resultado é distinto pois se está comparado um acesso sequencial (com ponteiros) e um acesso aleatório (com variáveis). Lembrando que uma das principais características da "liguagem C" é o tratamento interno das variáveis como ponteiros. Uma comparação correta seria comparar uma rotina de acesso aleatório utilizando ponteiros e variáveis (duas abordagens sobre a mesma questão buscada).
O acesso da array também é sequencial e qualquer compilador moderno hoje detecta isso e tira proveito disso.
Estranho, pois em C uma função que recebe um parâmetro int array[] é a mesma coisa que uma que recebe um argumento int *array. Essa diferença deve ser por causa do compilador, pois as duas formas são iguais.
Exatamente. Qualquer compilador hoje geraria o mesmo código.
Mas o compilador e o modelo de microcontrolador também pode te dar resultados diferentes.
agora tem que fazer um speedrun de quantos segundos leva até conseguir colocar uma falha de segurança no sistema sem o intuito de causar falha de segurança.
Olá Prof. Wagner, tudo bem? Grato pelo vídeo e espero que essa situação no RS melhore o mais rápido possível.
Também sou professor de programação em linguagem C e sempre considerei "array[i]" equivalente a "*(array + i)", mesmo sendo os códigos de máquina gerados ligeiramente diferentes. Nesse vídeo, fiquei curioso se, na instrução "for" da função "sum_array_ptr", "sum += *(ptr + i);" teria o mesmo desempenho que "sum += *ptr; ptr++;" em microcontroladores. Outra dúvida: Haveria ganho ao substituir a instrução "register int i;" por "register int *ptr = array;" conforme o código seguinte?
int sum_array_ptr(int *array, int size)
{
int sum = 0;
register int *ptr = array;
int *ptr_final = ptr + size;
while (ptr < ptr_final)
{
sum += *ptr;
ptr++;
}
return sum;
}
Abs.
sum += *(ptr + i);: Nesta instrução, você está acessando o valor no endereço apontado por ptr + i, onde i é um contador que aumenta a cada iteração do loop. Isso significa que, a cada iteração, o processador precisa calcular o endereço que está i posições à frente de ptr, o que pode exigir operações adicionais de adição e desreferenciação de ponteiro. Essas operações extras podem afetar o desempenho em microcontroladores, especialmente se a otimização do compilador não conseguir simplificar essas operações.
sum += *ptr; ptr++;: Nesta instrução, você simplesmente acessa o valor apontado por ptr e, em seguida, incrementa o ponteiro ptr. Esta abordagem pode ser mais eficiente em microcontroladores, pois não envolve cálculos adicionais de endereço a cada iteração. Apenas a desreferenciação do ponteiro e o incremento do ponteiro são necessários.
Na instrução sum += *ptr; ptr++; o desempenho é ligeiramente melhor, pois simplesmente acessamos o valor apontado por ptr e, em seguida, incrementa o ponteiro ptr. Em sum += *(ptr + i); você está acessando o valor no endereço apontado por ptr + i, onde i é um contador que aumenta a cada iteração do loop. Isso significa que, a cada iteração, o processador precisa calcular o endereço que está i posições à frente de ptr, o que pode exigir operações adicionais de adição.
Em sua outra dúvida, não há ganho em substituir register int i; por register int *ptr = array; no seu código.
abs!
Top sua aula professor!!!
Obrigado!
Excelente !!!
Gostei ... um abraço
Valeu Daniel! Abraço!
Perfeito
Qual simulador pra simular programas em C?
muito interessante
Esse vídeo me fez passar a última hora estudando ponteiros em C. No meio do meu estudo me deparei com a seguinte afirmação: "A indexação array[i] é traduzida pelo compilador em aritmética de ponteiros nos bastidores."
Baseado nessa informação e no seus 2 códigos, um percorrendo o array por indexação e outro com ponteiros, o compilador não traduziria ambos para as mesmas instruções? Você respondeu isso no vídeo, mostrando que com ponteiros o processamento é mais rápido, e foi ai que minha cabeça explodiu, POR QUÊ é mais rápido!? 🤣
Sua constatação foi excelente Gustavo e meu objetivo com o vídeo foi atingido. Fazer a galera estudar mais os ponteiros. Vou esclarecer a questão para você. Compiladores modernos são muito eficientes e podem otimizar muitas dessas diferenças. No entanto, a forma com ponteiros é muitas vezes mais simples de otimizar pelo compilador, já que as operações são mais diretas e há menos cálculos repetidos. O acesso sequencial direto que o código com ponteiros provê tende a ser melhor preditível do que os cálculos de endereços repetidos.
O que ocorre é que ao usar um compilador bastante eficiente em otimizações, geralmente temos a otimização correta em ambos os casos, como você observou. Na prática, apliquei os testes em MikroC, que apresenta um compilador proprietário dedicado a arquiteturas reduzidas, que são os microcontroladores, o que não gerou tal otimização.
@@canalwrkits perfeito. Obrigado
Qual vc recomenda, c ou c++? Excelente vídeo
Muito obrigado Anderson! Recomendo fortemente ambas as linguagens. Para começar, Linguagem C. Temos o curso Definitivo, é o mais completo do mercado: go.hotmart.com/N48026554Y
Bons estudos!
@@canalwrkits Muito obrigado pela resposta!!!!
Ponteiros são ótimos mas existe ressalvas, Ponteiros deixam o código mais complexo de leitura e manutenção. Ponteiros não possui proteção para acesso a uma memória nula isso pode quebrar o código. Ponteiro podem apontar para endereços de memórias livres(endereços de memória que não foram alocadas) causando quebra do código. Ponteiros não são mapeados, ou seja, você pode perfeitamente acessar um endereço de memoria que nao existe e isso quebra o código em tempo de execução. Ponteiros a maior parte dos erros dos ponteiros são descobertos apenas em tempo de execução. Ponteiros que alocam memória ai que a coisa pode ficar feia mesmo. Tenho estudado sobre hackeamento de sistemas embarcados, e softwares com ponteiros são mais fáceis de ler o assembler e hackear. No meu modo de programar utilizo ponteiro apenas em situações de eficiência de busca e calculo, no processo normal do codigo não utilizo, mesclar as dois paradigmas na minha visão é o ideal, cada qual na sua finalidade.
Ótimas observações Junior! É o que recomendo também.
Vlw
Uma pergunta, pq usar "sizeof(arr) / sizeof(arr[0]) ??
Nao seria mais facil usar so o sizeof(arr) ou sizeof(arr) -1?
Ou muda alguma coisa nesse contexto?
Em C, sizeof() de um array retorna o total de bytes dele. Daí você tem que dividir pelo total de bytes do tipo de variável que ele armazena para obter o total de elementos do array.
Exemplo: sizeof(arr)/sizeof(arr[0])
Ou, nesse caso: sizeof(arr)/sizeof(int)
@@dfepradointeressante, eu só mexia com C++ e lá é diferente, bom saber, obrigado
SUPER LIKE
Como funciona, Professor? Estou querendo adquirir o curso de Linguagem C.
Acesse o link: go.hotmart.com/N48026554Y e faça a aquisição.
Ao confirmar o pagamento, você receberá o link de acesso ao curso por email. Então é só acompanhar as aulas. O acesso é vitalício. Aguardo você no curso!
@@canalwrkits Obrigado
Fantástico!
Aqui se mata a cobra e se mostra o ponteiro! kkkkkkkk.
Valeu demais!
Exatamente hahah
e a segurança se não apontar direito ?
Usemos ponteiros com cautela.
@@canalwrkits teria como repetir o teste porem aplicando as correções de segurança pra ver quantos ms eles comem ?
seu pai tá bem?
Sim. Apenas danos materiais severos. A casa inteira e metade da empresa.
Quase 20% mais eficiente!!
cheguei. like 1
👏👏👏👏👏👏👏👏👏👏
E a casa branca queimando C/C++... Rapaz, é de lascar.
Sensacionalismo. C/C++ são indestrutíveis.
@@canalwrkits Creio que sim, mudança na administração pública e querem pagar de modernões(Rust é a linguagem "queer", é cada uma viu), muita besteira num documento só.
:)