O interpretador de comandos bash oferece suporte para manipulação de vetores esparsos, permitindo criar estruturas de dados indexadas sem necessidade de continuidade nos índices.
Definição de Arrays
Existem duas formas principais de inicializar um vetor:
nome=(valor1 valor2 valor3)
Ou utilizando índices explícitos, que podem ser descontínuos:
nome=([0]=valor1 [5]=valor2 [10]=valor3)
Acessando Elementos
Para obter um elemento específico, utiliza-se a sintaxe:
${nome[índice]}
Operações com Todos os Elementos
Pararetrieve todos os elementos do vetor:
${nome[*]}
${nome[@]}
Informações de Tamanho
Para verificar a quantidade de elementos:
${#nome[*]}
${#nome[@]}
Para obter o comprimento de um elemento específico:
${#nome[índice]}
Slice de Arrays
Extrair porções do vetor:
${nome[*]:posição:quantidade}
${nome[@]:posição:quantidade}
Exercícios Propostos
1. Verificar se o diretório "dados" existe no diretório atual; caso contrário, criá-lo. Copiar todos os arquivos regulares para esse diretório e contar a quantidade transferida.
2. Utilizando vetores, contar todos os arquivos no diretório pessoal do usuário:
arquivos=($(ls ~))
echo ${#arquivos[*]}
3. Contar argumentos informados na linha de comando:
parametros=($*)
echo ${#parametros[*]}
4. Contar arquivos com extensão ".c" no diretório pessoal.
Estrutura de Projetos Multi-arquivo
Projetos de maior porte organizados em vários arquivos fonte e cabeçalhos:
- principal.c - contém a função main()
- modulo.c - implementa funções específicas
- cabeçalho.h - declarações e definições públicas
Conteúdo de um Arquivo de Cabeçalho
Os arquivos .h geralmente incluem:
- Inclusão de outros cabeçalhos
- Declarações de funções
- Definições de tipos estruturados
- Constantes simbólicas
- Typedef para tipos personalizados
- Declarações de variáveis globais
Diferença entre aspas e Colchetes Angulares
#include <stdio.h>
#include "minha_funcao.h"
A diferença está no caminho de busca: colchetes angulares pesquisam apenas no diretório sistema de includes, enquanto aspas首先 verificam o diretório local e, se não encontrar, partem para o diretório sistema.
Compilação Condicional
O pré-processador decide quais trechos de código serão compilados baseado em condições definidas.
Verificação de Definição de Macros
#ifdef MACRO
código_quando_definido
#else
código_quando_nao_definido
#endif
Verificação de Valor Lógico
#if CONDIÇÃO
código_se_verdadeiro
#else
código_se_falso
#endif
Proteção Contra Inclusão Duplicada
#ifndef IDENTIFICADOR
#define IDENTIFICADOR
/* conteúdo do cabeçalho */
#endif
Esta técnica evita que o mesmo arquivo seja processado múltiplas vezes durante a compilação.
Fases de Compilação com GCC
O compilador GCC processa o código através de quatro etapas distintas:
1. Pré-processamento
Expansiona macros, inclui arquivos, remove comentários. Não verifica syntax errors:
gcc -E fonte.c -o fonte.i
2. Compilação
Converte o arquivo pré-processado para linguagem assembly, verificando erros de syntax:
gcc -S fonte.i -o fonte.s
3. Montagem
Traduz o código assembly para código de máquina (formato objeto):
gcc -c fonte.s -o fonte.o
4. Linkedição
Combina arquivos objeto e bibliotecas para gerar o executável:
gcc fonte.o -o executavel
Comando simplificado: gcc programa.c -o programa gera o binário diretamente.
Utilizando o Make
O Make é um utilitário que gerencia a construção de projetos, compilando apenas os arquivos modificados desde a última build.
Funcionamento
Ao modificar apenas alguns arquivos fonte, o Make identifica as alterações através de timestamps e recompila somente os afetados, economizando tempo de compilação.
Arquivo Makefile
O Makefile define regras de construção do projeto:
alvo: dependências
comando
Exemplo Prático
app: principal.o utilitario.o
gcc principal.o utilitario.o -o app
principal.o: principal.c
gcc -c principal.c -o principal.o
utilitario.o: utilitario.c
gcc -c utilitario.c -o utilitario.o
Alvos Especiais
.PHONY: limpar
limpar:
rm -f *.o app
Definir alvo como .PHONY previne conflitos quando existe arquivo com mesmo nome.
Variáveis Personalizadas
Variáveis em Makefile usam sintaxe $(nome):
- = - atribuição recursiva
- := - atribuição imediata
- += - concatenação
- ?= - atribuição condicional
Variáveis Pré-definidas
- CC - compilador C (padrão: cc)
- CFLAGS - opções do compilador
- RM - comando de remoção (padrão: rm -f)
Versão Otimizada do Mkaefile
PROGRAMA=app
FONTES=$(wildcard *.c)
OBJETOS=$(patsubst %.c,%.o,$(FONTES))
CC=gcc
FLAGS=-c -g -Wall
all: $(PROGRAMA)
$(PROGRAMA): $(OBJETOS)
$(CC) $^ -o $@
%.o: %.c
$(CC) $(FLAGS) $< -o $@
.PHONY: limpar
limpar:
$(RM) $(OBJETOS) $(PROGRAMA)
Variáveis Automáticas
- $< - primeira dependência
- $@ - nome do alvo
- $^ - todas as dependências (sem duplicatas)
Funções Úteis
wildcard -Localiza arquivos conforme padrão:
$(wildcard *.c)
patsubst -Substitui padrões em strings:
$(patsubst %.c,%.o,arquivo1.c arquivo2.c)
Resultado: arquivo1.o arquivo2.o