Sobre a eficiência de execução do código da linguagem C

A eficiência de execução de que falamos geralmente é a sobrecarga do sistema gerada usando o mesmo algoritmo para concluir o mesmo cálculo sob as mesmas condições de entrada.No momento, geralmente prestamos mais atenção ao tempo de execução adicional. O código escrito em todos os idiomas acabará sendo executado e deve ser convertido em código de máquina. É mais eficiente realizar a mesma coisa em menos tempo.

Vamos falar sobre como melhorar a eficiência de execução do programa de linguagem C.

1. Tente evitar chamar funções de atraso

 

Um programa sem sistema operacional pode ser executado ciclicamente apenas em (1). Se você chamar uma grande quantidade de atraso, ele consumirá recursos da CPU. O atraso é equivalente a deixá-lo descansar aqui, apenas interrompido Somente o interior será executado. Se você acabou de executar um programa em que o LED pisca uma vez por segundo, é muito simples, você pode chamar diretamente a função de atraso, mas em projetos reais, muitas vezes há muitas coisas para fazer no grande ciclo, não para ocasiões com altos requisitos em tempo real Também.

 

Para evitar o uso de atraso, você pode usar a interrupção do timer para gerar um bit de flag.Quando o bit de flag de tempo estiver definido, você só precisará detectar o bit de flag no programa principal, configurá-lo para executar uma vez e depois limpar o flag. Farei outras coisas em outros momentos, em vez de esperar aqui. O melhor exemplo é a exibição do tubo nixie, que usa a exibição do tom de interrupção. Depois, há a detecção da tecla. O procedimento geral é fazer enquanto (tecla!) Aguardar a liberação da tecla. Se a tecla for mantida pressionada, o programa a seguir nunca será executado e morrerá aqui. Na verdade, você pode criar um logotipo da tecla para detectar a queda Bordas e bordas ascendentes podem evitar esse problema.

2. O código deve ser o mais conciso possível para evitar duplicação

 

Vi a parte do código exibida no tubo digital escrita no livro que aprendeu o MCU em 10 dias, selecionou um pouco e, em seguida, enviou os dados, selecionou um pouco e, em seguida, enviou os dados e o terminou por sua vez. A taxa de repetição de código é muito alta, o que não apenas ocupa muita memória de classe, mas também possui baixa eficiência de execução e baixa legibilidade. Apenas implementa a função. A programação real pode ser um loop, para loop ou loop while. Esse código parece mais nivelado.

3. Uso razoável de definições de macro

 

Se uma variável ou registro for usado com frequência no programa, você poderá usar a definição de macro para definir um novo nome. Essa vantagem é conveniente para a modificação. Por exemplo, P1 conectado ao barramento de terminal de dados do LCD. Agora você deseja mudar para P0, então você só precisa modificar a definição de macro aqui. Quando o compilador compila, ele substitui automaticamente o nome definido pelo nome real. O nome

4. Use o menor tipo de dados possível

 

Por exemplo, o intervalo de valores de uma variável é de 0 a 255, então é definido como unsignedchar, é claro, também pode ser definido como unsignedint, mas isso causa um desperdício de memória e a eficiência da operação é menor.

 

Se os dados não tiverem um número negativo, tente defini-lo como um tipo não assinado. Você deve evitar ser definido como um tipo de dados de ponto flutuante ou um tipo de precisão dupla (8 bytes) .Esses dois tipos consomem muitos recursos da CPU ao computar.

 

Por exemplo, a faixa de tensão de coleta é de 0 a 5V, com precisão de três casas decimais, você pode expandir os dados coletados em 1000 vezes, mesmo se o máximo for de apenas 5000, coletar várias vezes para criar um algoritmo de filtragem e, finalmente, precisar calcular a tensão. É suficiente adicionar um ponto decimal após o primeiro dígito e a variável é definida como uma variável não assinada.

5. Evite usar multiplicação e divisão

 

Multiplicação e divisão consome recursos da CPU. Observando o código de montagem, você encontrará que uma operação de multiplicação e divisão compilará 10 ou mesmo dezenas de linhas de código. Se for multiplicado por ou dividido por 2 até a enésima potência, poderá ser implementado com << ou >>. Essa operação de turno já é calculada em tempo de compilação, portanto o código é muito simples e a eficiência da operação é alta. Mas você precisa prestar atenção especial à prioridade dos operadores.

 

6. Tente usar operadores de atribuição composta

 

Qual é a diferença entre as duas expressões a = a + b e a + = b?

 

O primeiro é calcular o valor de a + b primeiro e, em seguida, salve-o no registro ACC e, em seguida, atribua o valor do registro ACC a a. Este último atribui diretamente o valor de a + b a, salvando uma etapa. Embora apenas uma instrução seja salva, e quando essa operação faz um loop milhares de vezes e dezenas de milhares de vezes? Então o efeito é óbvio.

 

Como outros- =, * =, / =,% =, etc. são os mesmos.

7. Tente não definir variáveis ​​globais

 

Primeiro, observe as semelhanças e diferenças entre variáveis ​​locais, variáveis ​​globais, variáveis ​​locais estáticas e variáveis ​​globais estáticas.

 

▶ Variáveis ​​locais:

As variáveis ​​definidas em uma função ou instrução composta são unidades de armazenamento alocadas na área de armazenamento dinâmico, alocadas dinamicamente quando chamadas e liberadas automaticamente quando a função ou instrução composta termina.

 

▶ Variáveis ​​locais estáticas:

Quando uma variável local é definida em uma função, se a declaração estática é adicionada, a variável é uma variável local estática e a unidade de armazenamento é alocada na área de armazenamento estático e não é liberada durante a execução do programa; as variáveis ​​locais estáticas só podem ser usadas na função Variáveis ​​locais estáticas são atribuídas no tempo de compilação (se nenhuma atribuição for feita no momento da definição, a atribuição padrão é 0 (para variáveis ​​numéricas) ou caracteres nulos (para variáveis ​​de caracteres)); variáveis ​​locais estáticas não são liberadas automaticamente após o término da chamada de função , Reter o valor após o término da chamada de função.

 

▶ Variáveis ​​globais:

As variáveis ​​definidas fora da função são denominadas variáveis ​​globais; as variáveis ​​globais são alocadas às unidades de armazenamento na área de armazenamento estático e não são liberadas durante a operação do programa. As funções no arquivo podem chamar a variável global e as funções em outros arquivos a variável global. Precisa adicionar instrução externa.

 

▶ Variáveis ​​globais estáticas:

Quando uma variável é definida fora da função, se a instrução staTIc for adicionada, a variável é uma variável global estática; a variável global estática é alocada a uma unidade de armazenamento na área de armazenamento estático e não é liberada durante a execução do programa.A variável global estática é atribuída em tempo de compilação (se Se nenhum processamento de atribuição for executado durante a definição, o valor padrão da atribuição é 0 (para variáveis ​​numéricas) ou caracteres nulos (para variáveis ​​de caracteres); ele só pode ser usado no arquivo atual.

 

▶ Resumo:

Em circunstâncias normais, é definida como uma variável local, que não apenas roda com mais eficiência, como também é fácil de transplantar. As variáveis ​​locais estão localizadas principalmente em registradores dentro do MCU. Na maioria dos MCUs, a velocidade de operação do uso de registradores é mais rápida que o armazenamento de dados, e as instruções são cada vez mais flexíveis, o que conduz à geração de código de melhor qualidade e os registros ocupados por variáveis ​​locais E o armazenamento de dados pode ser reutilizado em diferentes módulos.

 

Quando você precisar usar variáveis ​​em uma interrupção, precisará defini-las como variáveis ​​globais e adicionar volaTIle para impedir a otimização do compilador. Se os dados forem somente leitura, como o código quebrado do tubo digital, a biblioteca de fontes do módulo de caracteres chineses precisará ser colocada na ROM, para que a RAM possa ser salva, o microcomputador 51 de chip único será adicionado com o código e os microcomputadores avançados de chip único serão adicionados com modificação const.

8. Escolha o algoritmo e a estrutura de dados corretos

 

Você deve estar familiarizado com a linguagem do algoritmo e conhecer as vantagens e desvantagens de vários algoritmos.Para obter informações específicas, consulte os materiais de referência correspondentes, que são introduzidos em muitos livros sobre computadores. Substituir o método de pesquisa sequencial mais lento por um método de pesquisa binária mais rápida ou fora de ordem e inserir ou classificar bolhas por classificação rápida, classificação por mesclagem ou classificação por raiz podem melhorar bastante a eficiência da execução do programa. Também é importante escolher uma estrutura de dados adequada. Um ponteiro é uma variável que contém um endereço e a variável apontada por ele pode ser endereçada. O uso de um ponteiro pode passar facilmente de uma variável para a próxima variável, portanto, é particularmente adequado para a operação de um grande número de variáveis. Matrizes e instruções de ponteiro têm um relacionamento muito próximo.De um modo geral, os ponteiros são mais flexíveis e concisos, enquanto as matrizes são mais intuitivas e fáceis de entender. Para a maioria dos compiladores, o uso de ponteiros é mais curto que o código gerado usando matrizes e a eficiência de execução é maior. Em Keil, por outro lado, o código gerado usando uma matriz é mais curto que o ponteiro usado.

9. Use compilação condicional

 

Em geral, ao compilar um programa em linguagem C, todos os programas participam da compilação, mas, às vezes, espera-se que parte do conteúdo seja compilado somente quando determinadas condições forem atendidas, o que é uma compilação condicional. A compilação condicional pode escolher diferentes escopos de compilação de acordo com a situação real, gerando códigos diferentes.

 

10. Incorporando tradução killer de compilação

 

A linguagem assembly é a linguagem de computador mais eficiente.No desenvolvimento geral do projeto, a linguagem C geralmente é usada para desenvolvimento, porque a incorporação de assembly afetará a portabilidade e legibilidade da plataforma, e as instruções de montagem de diferentes plataformas são incompatíveis. Mas para alguns programadores persistentes que exigem que o programa obtenha a máxima eficiência de execução, todos incorporam o assembly na linguagem C, ou seja, "programação híbrida".

Publicado 13 artigos originais · elogiado 4 · visitas 767

Acho que você gosta

Origin blog.csdn.net/yuechifanfan/article/details/105570128
Recomendado
Clasificación