A Biblioteca Padrão
A biblioteca padrão é como uma caixa de ferramentas — você não precisa forjar seu próprio martelo e chave de fenda, basta pegá-los e usá-los. Entender o que cada ferramenta faz ajuda você a escolher a certa.
math.h Operações Matemáticas
Usar funções matemáticas requer incluir o cabeçalho e linkar a biblioteca matemática:
#include <math.h>
Compile com a flag -lm: gcc programa.c -lm.
Funções Matemáticas Comuns
| Função | Finalidade | Exemplo |
|---|---|---|
fabs(x) |
Valor absoluto | fabs(-3.5) → 3.5 |
sqrt(x) |
Raiz quadrada | sqrt(16.0) → 4.0 |
pow(x, y) |
x elevado à potência y | pow(2.0, 10.0) → 1024.0 |
ceil(x) |
Arredondar para cima | ceil(3.2) → 4.0 |
floor(x) |
Arredondar para baixo | floor(3.8) → 3.0 |
round(x) |
Arredondar para o mais próximo | round(3.5) → 4.0 |
fmod(x, y) |
Resto de ponto flutuante | fmod(7.5, 2.5) → 0.0 |
log(x) |
Logaritmo natural | log(2.718) → 1.0 |
log10(x) |
Logaritmo comum | log10(100.0) → 2.0 |
sin(x) |
Seno | sin(3.14/2) → 1.0 |
cos(x) |
Cosseno | cos(0.0) → 1.0 |
tan(x) |
Tangente | tan(0.0) → 0.0 |
rad = grau * 3.14159265 / 180.0.
Exemplo
Calcular a distância entre dois pontos:
#include <stdio.h>
#include <math.h>
typedef struct {
double x;
double y;
} Point;
double distance(Point a, Point b) {
double dx = a.x - b.x;
double dy = a.y - b.y;
return sqrt(dx * dx + dy * dy);
}
int main(void) {
Point p1 = {3.0, 4.0};
Point p2 = {0.0, 0.0};
printf("Distância: %.2f\n", distance(p1, p2));
return 0;
}
Distância: 5.00
stdlib.h Utilitários Gerais
Números Aleatórios
int rand(void);
void srand(unsigned int seed);
rand() retorna um inteiro pseudo-aleatório entre 0 e RAND_MAX. Sem chamar srand, cada execução do programa produz a mesma sequência de números aleatórios.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
srand((unsigned int)time(NULL));
for (int i = 0; i < 5; i++) {
printf("%d ", rand());
}
printf("\n");
for (int i = 0; i < 5; i++) {
printf("%d ", rand() % 100);
}
printf("\n");
return 0;
}
1804289383 846930886 1681692777 1714636915 1957747793
83 86 77 15 93
rand() % N não fornece boa aleatoriedade na maioria das implementações — bits baixos podem seguir um padrão. Para cenários que requerem aleatoriedade de alta qualidade, use um gerador de números aleatórios mais avançado.
Conversão de Tipos
| Função | Finalidade |
|---|---|
atoi(str) |
String para int |
atol(str) |
String para long |
atof(str) |
String para double |
strtol(str, &end, base) |
String para long (com base) |
strtod(str, &end) |
String para double (com detecção de erro) |
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int a = atoi("42");
double b = atof("3.14");
long c = strtol("0xFF", NULL, 16);
printf("a = %d\n", a);
printf("b = %.2f\n", b);
printf("c = %ld\n", c);
char *end;
long d = strtol("123abc", &end, 10);
printf("d = %ld, Parte não convertida: %s\n", d, end);
return 0;
}
a = 42
b = 3.14
c = 255
d = 123, Parte não convertida: abc
atoi não pode detectar erros — entrada inválida retorna 0, o que é indistinguível de um 0 legítimo. Prefira strtol/strtod, que permitem determinar se a conversão foi bem-sucedida através do ponteiro end.
Gerenciamento de Memória Dinâmica
void *malloc(size_t size);
void *calloc(size_t count, size_t size);
void *realloc(void *ptr, size_t size);
void free(void *ptr);
malloc: alocasizebytes, não inicializacalloc: alocacount*sizebytes, inicializa tudo com 0realloc: redimensiona memória previamente alocada, pode mover o endereçofree: libera memória
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int *arr = calloc(5, sizeof(int));
if (arr == NULL) {
return 1;
}
for (int i = 0; i < 5; i++) {
arr[i] = i * 10;
}
int *new_arr = realloc(arr, 10 * sizeof(int));
if (new_arr == NULL) {
free(arr);
return 1;
}
arr = new_arr;
for (int i = 5; i < 10; i++) {
arr[i] = i * 10;
}
for (int i = 0; i < 10; i++) {
printf("%d ", arr[i]);
}
printf("\n");
free(arr);
return 0;
}
0 10 20 30 40 50 60 70 80 90
realloc falha, ela retorna NULL mas a memória original não é liberada! Portanto você deve usar uma variável temporária para receber o valor de retorno do realloc — em caso de falha, você ainda pode liberar a memória original.
Ordenação e Busca
qsort
void qsort(void *base, size_t count, size_t size,
int (*compare)(const void *, const void *));
Regras da função de comparação: retorna negativo se a < b, 0 se igual, positivo se a > b.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int cmp_int(const void *a, const void *b) {
return *(const int *)a - *(const int *)b;
}
int cmp_str(const void *a, const void *b) {
return strcmp(*(const char )a, *(const char )b);
}
int main(void) {
int nums[] = {42, 17, 8, 95, 3, 61};
int n = sizeof(nums) / sizeof(nums[0]);
qsort(nums, n, sizeof(int), cmp_int);
for (int i = 0; i < n; i++) {
printf("%d ", nums[i]);
}
printf("\n");
const char *names[] = {"Alice", "Bob", "Charlie", "Diana"};
int m = sizeof(names) / sizeof(names[0]);
qsort(names, m, sizeof(char *), cmp_str);
for (int i = 0; i < m; i++) {
printf("%s ", names[i]);
}
printf("\n");
return 0;
}
3 8 17 42 61 95
Alice Bob Charlie Diana
bsearch
void *bsearch(const void *key, const void *base, size_t count,
size_t size, int (*compare)(const void *, const void *));
Realiza busca binária em um array ordenado. Retorna um ponteiro para o elemento encontrado, ou NULL se não encontrado.
#include <stdio.h>
#include <stdlib.h>
int cmp_int(const void *a, const void *b) {
return *(const int *)a - *(const int *)b;
}
int main(void) {
int nums[] = {3, 8, 17, 42, 61, 95};
int n = sizeof(nums) / sizeof(nums[0]);
int key = 42;
int *result = bsearch(&key, nums, n, sizeof(int), cmp_int);
if (result != NULL) {
printf("Encontrado %d no índice %ld\n", key, result - nums);
} else {
printf("%d não encontrado\n", key);
}
return 0;
}
Encontrado 42 no índice 3
time.h Tratamento de Tempo
Funções de Tempo
| Função/Tipo | Finalidade |
|---|---|
time_t |
Tipo de tempo (geralmente segundos desde 1970-01-01) |
time(&t) |
Obter tempo atual |
clock() |
Obter ticks de clock da CPU usados pelo programa |
localtime() |
Converter para struct de tempo local |
gmtime() |
Converter para struct de tempo UTC |
strftime() |
Formatar tempo como string |
difftime() |
Calcular diferença entre dois tempos (segundos) |
struct tm
struct tm {
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst;
};
tm_mon varia de 0-11 (0 = Janeiro), tm_year é o número de anos desde 1900, e tm_wday usa 0 para Domingo.
Exemplo
#include <stdio.h>
#include <time.h>
int main(void) {
time_t now = time(NULL);
struct tm *local = localtime(&now);
char buf[64];
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", local);
printf("Hora atual: %s\n", buf);
printf("Hoje é o dia %d da semana (0=Dom)\n", local->tm_wday);
return 0;
}
Hora atual: 2025-03-15 14:30:22
Hoje é o dia 6 da semana (0=Dom)
Cronometragem de Programa
#include <stdio.h>
#include <time.h>
int main(void) {
clock_t start = clock();
volatile long sum = 0;
for (long i = 0; i < 100000000L; i++) {
sum += i;
}
clock_t end = clock();
double elapsed = (double)(end - start) / CLOCKS_PER_SEC;
printf("Tempo decorrido: %.3f segundos\n", elapsed);
return 0;
}
Tempo decorrido: 0.235 segundos
clock() mede tempo de CPU, não tempo de relógio de parede. Se o programa tem esperas de sleep ou I/O, esse tempo não é contado. Use difftime para medir o tempo decorrido real.
ctype.h Tratamento de Caracteres
| Função | Condição Testada |
|---|---|
isalpha(c) |
Letra |
isdigit(c) |
Dígito |
isalnum(c) |
Letra ou dígito |
isupper(c) |
Letra maiúscula |
islower(c) |
Letra minúscula |
isspace(c) |
Espaço em branco (espaço, tab, nova linha, etc.) |
ispunct(c) |
Pontuação |
isprint(c) |
Caractere imprimível |
toupper(c) |
Converter para maiúscula |
tolower(c) |
Converter para minúscula |
Essas funções requerem um valor unsigned char ou EOF como argumento. Passar um valor char negativo é comportamento indefinido.
Exemplo
Contar letras, dígitos e outros caracteres em uma string:
#include <stdio.h>
#include <ctype.h>
int main(void) {
char str[] = "Olá, Mundo! 123";
int letters = 0, digits = 0, others = 0;
for (int i = 0; str[i] != '\0'; i++) {
if (isalpha((unsigned char)str[i])) {
letters++;
} else if (isdigit((unsigned char)str[i])) {
digits++;
} else {
others++;
}
}
printf("Letras: %d, Dígitos: %d, Outros: %d\n", letters, digits, others);
return 0;
}
Letras: 10, Dígitos: 3, Outros: 6
assert.h Asserções
void assert(int expression);
Quando a expressão é falsa, o programa termina e exibe uma mensagem de erro (nome do arquivo, número da linha, expressão). Definir a macro NDEBUG antes de #include <assert.h> desabilita todas as asserções.
#include <stdio.h>
#include <assert.h>
double safe_divide(double a, double b) {
assert(b != 0 && "Divisor não pode ser zero");
return a / b;
}
int main(void) {
printf("10 / 2 = %.1f\n", safe_divide(10.0, 2.0));
printf("10 / 0 = %.1f\n", safe_divide(10.0, 0.0));
return 0;
}
10 / 2 = 5.0
Assertion failed: b != 0 && "Divisor não pode ser zero", file main.c, line 5
assert é impresso, então escrever "Divisor não pode ser zero" é mais eficaz que um comentário — quando a asserção falha, você pode ver imediatamente o motivo.
❓ Perguntas Frequentes
P: Por que rand() produz a mesma sequência em cada execução? R: Nenhuma chamada a srand foi feita para definir a semente aleatória. A semente padrão é 1, então a sequência é fixa. Use
srand(time(NULL))para semear com o tempo atual.
P: Por que a função de comparação do qsort usa ponteiros void? R: qsort é uma função genérica que não sabe que tipo está ordenando. Ponteiros void podem apontar para qualquer tipo, e a função de comparação os converte de volta ao tipo específico internamente.
P: Por que argumentos de funções ctype.h devem ser convertidos para unsigned char? R: Se char é com sinal, caracteres com o bit alto definido podem ser valores negativos, o que é comportamento indefinido quando passado para funções ctype. Converter para unsigned char garante que o valor esteja na faixa 0-255.
P: Qual a diferença entre assert e uma verificação if? R: assert verifica coisas que nunca deveriam acontecer (erros lógicos) durante o desenvolvimento, e desaparece quando NDEBUG é definido. Verificações if tratam erros de tempo de execução que podem ocorrer e estão sempre presentes.
📖 Resumo
math.hfornece funções matemáticas; funções trigonométricas usam radianos; compile com-lmrand/srandgeram números pseudo-aleatórios; usesrand(time(NULL))para semear com o tempostrtol/strtodsão mais seguros queatoi/atofe podem detectar erros de conversãoqsort/bsearchsão as ferramentas de ordenação e busca da biblioteca padrão, exigindo funções de comparação personalizadasasserté para depuração em desenvolvimento; desabilite em builds de release viaNDEBUG
📝 Exercícios
- Escreva um programa que gere 100 inteiros aleatórios de 1 a 1000, ordene-os com qsort e exiba os valores máximo e mínimo
- Escreva um programa que use clock() para comparar a diferença de tempo entre bubble sort e qsort em 10.000 inteiros
- Escreva uma função que use funções ctype.h para implementar conversão de maiúsculas/minúsculas de string (entrada uma string, saída versão toda maiúscula e toda minúscula)



