Skip to content
SPONSORS
By Corsi
Picture of Corsi
Corsi

Head File ​

!!! note "Rule 2.0" Todo head file (.h) deve ser criado com include guard.

!!! note "Rule 2.1" Não ter implementação de código em head file (.h).

Head file (.h) é um arquivo de texto com códigos C que será processado de forma diferente do arquivo .c e que possibilita a melhor estruturação de um programa, sendo possível estruturar o código de uma forma mais organizada, possibilitando a criação de bibliotecas (nada parecido com python), deixando o programa mais estruturado.

Para isso funcionar direito o head file deve possuir um recurso que iniba a inclusão redundante (mais de uma vez) no processo de compilação, evitando a redefinição de defines, tipos ou funções. Além desse recurso, não podemos ter no arquivo .h códigos que gerem instruções (ou seja, não podemos implementar uma função no head)!

Exemplo ​

O exemplo a seguir demonstra um ==uso errado== do arquivo .h:

c
// main.h
int var; 

int bar(int b) {
    if (b > 2) 
        return 0;
    return 1;
}
c
// main.c
#include "main.h"

int main(void){
    int a = bar(12);
}

O código anterior viola a regra 2.0 e a regra 2.1 gerando o seguinte erro:

Forma correta ​

Para desenvolvermos bons códigos em C devemos usar a seguinte estrutura de arquivos .c e .h:

  • .c: É onde efetivamente implementamos nossos códigos que geram instruções.
  • .h: Arquivo de cabećalho que auxilia na organizacão do código.

!!! warning Toda implementação de função deve ocorrer no arquivo .c!

O diagrama a seguir ilustra como devemos tratar os diferentes tipos de arquivos:

Estes arquivos quando compilados devem gerar arquivos .o[^1], reparem que o arquivo foo.c virou um objeto foo.o, isso otimiza todo o processo de compilação, o gcc não precisa recompilar o foo.c se não houve mudanças nele.

Mas para isso funcionar corretamente temos que implementar algo chamado de include guard nos arquivos .h, o include guard limita a inclusão do head apenas uma vez no processo de compilação. O código correta fica assim:

c
// main.c
#include "bar.h"

void main(){...}
c
// bar.h
#ifndef BAR_H
#define BAR_H

int bar(int b);

#endif
c
// bar.c
#include "bar.h"

int bar(int b){
...
}

!!! exercise choice two-cols Qual o par de códigos correto para um arquivo pisca.c e pisca.h que implementa a funcão void led(void)?

=== "(a)"
    `pisca.h`
    ```c
    void led(coid){
        pio_set(...); 
        pio_clear(...);
    }
    ```

    `pisca.c`
    ```c
    #ifndef PISCA_H
    #define PISCA_H
    
    #include "pisca.h"
    
    #endif        
    ```
    
=== "(b)"

    `pisca.h`
    ```c
    #ifndef PISCA_H
    #define PISCA_H
    
    #include "pisca.h"
    
    #endif
    ```
    
    `pisca.c`
    ```c
    #include "pisca.h"
    
    void led(coid){
        pio_set(...); 
        pio_clear(...);
    }
    ```
    
=== "\(c\)"
    `pisca.h`
    ```c
    #ifndef PISCA_H
    #define PISCA_H
    
    #include "pisca.h"
    
    void led(coid);
    
    #endif
    ```
    
    `pisca.c`
    ```c
    #include "pisca.h"
    
    void led(coid){
        pio_set(...); 
        pio_clear(...); 
    }
    ```
   
- [ ] 
- [ ] 
- [x] 

!!! answer
    O Item (C) é o único que possui todos os itens necessários:
    
    - Arquivo `.h` com include guard.
    - Arquivo `.h` com prototype das funcões.
    - Arquivo `.c` inclui arquivo `.h`.

!!! exercise choice two-cols Você sabe a diferença entre: #include "foo.h" e #include <foo.h>?

- [x] Sim
- [x] Não

!!! answer
    Usamos `" "` para quando queremos fazer o `include` de um arquivo que pertece ao projeto apenas e `< >` quando o arquivo é uma biblioteca do sistema!

Keyword extern ​

!!! tip Para que seu Head file acesse uma variável global que está na main.c, você precisa adicionar a keyword extern nessa variável dentro do arquivo head .h:

https://www.geeksforgeeks.org/understanding-extern-keyword-in-c/

Editando o CMakeList.txt ​

Você também vai precisar adicionar foo.c no arquivo CMakeList.txt:

c
add_executable(... main.c foo.c ...)

Praticando ​

Vamos praticar um pouco e corrigir as regras básicas de qualidade de código e boas práticas em sistemas embarcados, para isso crie um repositório pelo github classroom e então modifique os arquivos conforme indicado.

  1. Crie um repositório com o código exemplo acessando o github classroom!
  2. Analise o log do actions e verifique que o cppcheck executou e encontrou alguns erros.
  3. Corrigir o código e verificar se ainda continuamos com erros.