Funções de string (string.h)
Esta aula aborda as principais funções da biblioteca string.h em C: strlen, strcpy, strcat, strcmp e suas variações seguras (strncpy, strncat, strncmp). Também discute o problema do buffer overflow e boas práticas para evitar vulnerabilidades.
Em C, strings são arrays de caracteres terminados por '\0'. A biblioteca <string.h> oferece funções para manipular essas sequências de forma eficiente. Nesta aula, estudaremos as mais comuns: strlen, strcpy, strcat, strcmp e suas versões com limite de tamanho (strncpy, strncat, strncmp). Também veremos os riscos de buffer overflow e como evitá-los.
Dominar essas funções é essencial para programar em C com segurança e eficiência, especialmente em sistemas embarcados e software de baixo nível.
strlen, strcpy, strcat
strlen retorna o comprimento de uma string (sem contar o '\0'). strcpy copia uma string para outra, e strcat concatena (anexa) uma string ao final de outra. Todas esperam que o destino tenha espaço suficiente.
#include <stdio.h>
#include <string.h>
int main() {
char src[] = "Hello";
char dest[20];
size_t len = strlen(src); // len = 5
printf("Comprimento: %zu\n", len);
strcpy(dest, src); // dest = "Hello"
printf("Cópia: %s\n", dest);
strcat(dest, " World"); // dest = "Hello World"
printf("Concatenação: %s\n", dest);
return 0;
}No exemplo, dest tem 20 bytes, o suficiente para a concatenação. Se fosse menor, ocorreria buffer overflow.
strcmp
strcmp compara duas strings lexicograficamente (valor ASCII). Retorna 0 se iguais, negativo se a primeira é menor, positivo se maior.
#include <stdio.h>
#include <string.h>
int main() {
char str1[] = "apple";
char str2[] = "banana";
int result = strcmp(str1, str2);
if (result < 0) printf("%s vem antes de %s\n", str1, str2);
else if (result > 0) printf("%s vem depois de %s\n", str1, str2);
else printf("Iguais\n");
return 0;
}Para comparação parcial ou insensível a maiúsculas, use strncmp ou strcasecmp (POSIX).
strncpy e segurança
As funções strncpy, strncat e strncmp recebem um parâmetro de tamanho máximo para evitar estouro de buffer. strncpy copia no máximo n caracteres; se a origem for menor, preenche o resto com '\0'. Se for maior, não adiciona o terminador nulo — cuidado!
#include <stdio.h>
#include <string.h>
int main() {
char src[] = "Hello, world!";
char dest[6];
strncpy(dest, src, 5);
dest[5] = '\0'; // necessário!
printf("%s\n", dest); // "Hello"
// strncat
char dest2[20] = "Hello";
strncat(dest2, " World", 10);
printf("%s\n", dest2);
// strncmp
int cmp = strncmp("abcde", "abcxy", 3); // compara 3 chars: 0
printf("%d\n", cmp);
return 0;
}Boa prática: sempre garantir que a string destino seja terminada em nulo após strncpy. Prefira snprintf para cópia segura.
Buffer overflow
Buffer overflow ocorre quando se escreve além do limite de um array. As funções strcpy e strcat são vulneráveis. Exemplo clássico:
char buffer[10];
strcpy(buffer, "Esta string é muito longa!"); // overflow!Isso corrompe a memória adjacente, podendo causar falhas ou brechas de segurança (como em ataques de injeção). Para evitar:
- Use
strncpyestrncatcom o tamanho correto. - Use
snprintfpara formatar strings com limite. - Em C moderno, considere funções como
strlcpy(não padrão, mas disponível em alguns sistemas). - Sempre verifique o espaço disponível antes de copiar.
Boas práticas
- Sempre inicializar buffers com
char buffer[100] = {0};ou usarmemset. - Preferir funções com limite de tamanho (n versões).
- Usar
sizeofpara obter o tamanho do array (quando aplicável). - Evitar
gets(obsoleto); usarfgets.
Referências
- cppreference: string functions
- GNU C Library: String and Array Utilities
- SEI CERT C: STR00-C
- SEI CERT C: STR31-C
- OWASP: Buffer Overflow
Exercícios
- Escreva uma função que receba duas strings e retorne 1 se a primeira contém a segunda (substring), 0 caso contrário. Use apenas funções de
string.h. - Dado
char s1[20] = "Hello";echar s2[20] = "World";, usestrncpyestrncatpara obter"HelloWorld"ems1. Garanta que não haja overflow. - Explique por que
strncpy(dest, src, n)pode não terminar a string com '\0'. Dê um exemplo. - Qual a diferença entre
strcmpestrncmp? Mostre com um exemplo. - Escreva um programa que leia uma string do usuário (use
fgets) e a imprima de trás para frente usando apenas funções destring.h.
#include <string.h>
int contains(const char *str, const char *sub) {
return strstr(str, sub) != NULL;
}char s1[20] = "Hello";
char s2[20] = "World";
// s1 já tem "Hello", queremos concatenar "World"
// strncat já cuida do terminador
strncat(s1, s2, sizeof(s1) - strlen(s1) - 1);
// ou, se quiser copiar primeiro:
// char temp[20];
// strncpy(temp, s1, sizeof(temp)-1);
// temp[sizeof(temp)-1]='\0';
// strncat(temp, s2, sizeof(temp)-strlen(temp)-1);
// mas o exercício pede em s1, então concatenar diretamente é válido.strncpy copia no máximo n caracteres. Se a string origem for maior ou igual a n, ela não adiciona o '\0' no final, pois já usou todos os n bytes. Exemplo: char src[]="abcde"; char dest[3]; strncpy(dest, src, 3); → dest contém 'a','b','c' sem '\0'. Isso pode causar comportamento indefinido se dest for usada como string.strcmp compara toda a string até o '\0', enquanto strncmp compara apenas os primeiros n caracteres. Exemplo: strcmp("abcde", "abcxy") retorna negativo (pois 'd' < 'x'), mas strncmp("abcde", "abcxy", 3) retorna 0 (os 3 primeiros são iguais).#include <stdio.h>
#include <string.h>
int main() {
char str[100];
printf("Digite uma string: ");
fgets(str, sizeof(str), stdin);
str[strcspn(str, "\n")] = '\0'; // remove newline
size_t len = strlen(str);
for (size_t i = len; i > 0; i--) {
putchar(str[i-1]);
}
putchar('\n');
return 0;
}