Funções de string (string.h)
Esta aula aborda as principais funções da biblioteca string.h em C, como strlen, strcpy, strcat e strcmp, além de suas versões mais seguras (strncpy, strncat, strncmp). Também discute o problema de buffer overflow e boas práticas para manipulação de strings.
Em C, strings são representadas como arrays de caracteres terminados por um caractere nulo ('\0'). A biblioteca string.h fornece funções essenciais para manipular essas strings, como copiar, concatenar, comparar e obter o comprimento. No entanto, muitas dessas funções são propensas a erros de segurança, como o buffer overflow. Nesta aula, exploraremos as funções mais comuns, suas limitações e alternativas mais seguras.
Dominar essas funções é fundamental para escrever código C robusto e seguro. Veremos exemplos práticos e discutiremos como evitar armadilhas comuns.
strlen, strcpy, strcat
strlen retorna o comprimento de uma string, excluindo o caractere nulo. strcpy copia uma string de origem para um destino, sobrescrevendo o conteúdo do destino. strcat concatena (anexa) uma string de origem ao final de uma string de destino. Ambas as funções assumem que o buffer de destino tem espaço suficiente para o resultado.
Exemplo de uso:
#include <stdio.h>
#include <string.h>
int main() {
char src[] = "Hello";
char dest[20] = "World";
printf("Comprimento de src: %zu\n", strlen(src));
strcpy(dest, src);
printf("Após strcpy: %s\n", dest);
strcat(dest, "!");
printf("Após strcat: %s\n", dest);
return 0;
}Saída:
Comprimento de src: 5
Após strcpy: Hello
Após strcat: Hello!strcmp
strcmp compara duas strings lexicograficamente. Retorna 0 se forem iguais, um valor negativo se a primeira for menor e positivo se for maior. A comparação é baseada nos valores ASCII dos caracteres.
Exemplo:
#include <stdio.h>
#include <string.h>
int main() {
char str1[] = "apple";
char str2[] = "banana";
int result = strcmp(str1, str2);
if (result == 0) {
printf("Iguais\n");
} else if (result < 0) {
printf("str1 vem antes\n");
} else {
printf("str2 vem antes\n");
}
return 0;
}Saída:
str1 vem antesstrncpy e segurança
strncpy é uma versão mais segura de strcpy, pois copia no máximo n caracteres. No entanto, strncpy não adiciona automaticamente o terminador nulo se o limite for atingido, o que pode causar problemas. Além disso, se a string de origem for maior que n, a string de destino não será terminada em nulo. Por isso, é recomendado usar strncpy e garantir que o último caractere seja nulo, ou usar funções como snprintf.
Exemplo seguro:
#include <stdio.h>
#include <string.h>
int main() {
char src[] = "Hello, world!";
char dest[6];
strncpy(dest, src, sizeof(dest) - 1);
dest[sizeof(dest) - 1] = '\0'; // Garante terminação nula
printf("Dest: %s\n", dest);
return 0;
}Saída:
Dest: HelloBuffer overflow
Buffer overflow ocorre quando se escreve além dos limites de um buffer, sobrescrevendo memória adjacente. Isso pode levar a falhas de segurança, como execução de código arbitrário. Funções como gets, strcpy e strcat são particularmente perigosas se o tamanho do destino não for verificado. Para evitar, sempre use funções com limite de tamanho (strncpy, strncat, snprintf) e nunca use gets. Além disso, utilize fgets para leitura de entrada.
Exemplo de buffer overflow:
#include <stdio.h>
#include <string.h>
int main() {
char buffer[10];
strcpy(buffer, "Esta string é muito longa e causará overflow!");
printf("%s\n", buffer);
return 0;
}Esse código pode corromper a memória e causar comportamento indefinido.
Boas práticas
Sempre verifique o tamanho do buffer antes de copiar ou concatenar. Prefira funções como snprintf para formatar strings de forma segura. Use fgets em vez de gets. Documente as suposições sobre o tamanho das strings. Considere usar funções como strlcpy e strlcat (disponíveis em alguns sistemas) que garantem terminação nula.
Referências
Exercícios
-
Escreva uma função que receba duas strings e retorne 1 se forem iguais, 0 caso contrário, sem usar
strcmp.✓ Resposta:int str_igual(char *a, char *b) { while (*a && *b) { if (*a != *b) return 0; a++; b++; } return *a == *b; } -
O que há de errado no código abaixo? Corrija-o.
char nome[10]; strcpy(nome, "João"); printf("%s\n", nome);✓ Resposta:O buffer
nometem tamanho 10, e a string "João" tem 5 caracteres (incluindo o '\0'?), mas o problema é que a string "João" contém caracteres acentuados que em UTF-8 podem ocupar mais bytes (ex.: 'ã' ocupa 2 bytes). Na verdade, "João" em UTF-8 tem 5 bytes + nulo = 6 bytes, o que cabe em 10. No entanto, o código é tecnicamente correto, mas se a string fosse maior que 9 caracteres, haveria overflow. Uma versão segura seria usarstrncpyousnprintf. -
Use
strncpypara copiar a string "Programação em C" para um buffer de 15 bytes, garantindo terminação nula.✓ Resposta:char buffer[15]; strncpy(buffer, "Programação em C", sizeof(buffer) - 1); buffer[sizeof(buffer) - 1] = '\0'; -
Explique por que
getsé perigoso e qual função deve ser usada em seu lugar.✓ Resposta:getsnão verifica o tamanho do buffer, podendo causar buffer overflow. Deve ser substituída porfgets, que permite limitar o número de caracteres lidos. -
Escreva um programa que concatene duas strings de forma segura, usando
snprintf.✓ Resposta:#include <stdio.h> int main() { char dest[20] = "Hello, "; char src[] = "world!"; int len = snprintf(dest + strlen(dest), sizeof(dest) - strlen(dest), "%s", src); if (len >= sizeof(dest) - strlen(dest)) { printf("Buffer truncado\n"); } printf("%s\n", dest); return 0; }