Manuseio de string C - C string handling
Biblioteca padrão C |
---|
Tópicos gerais |
Diversos cabeçalhos |
A linguagem de programação C tem um conjunto de funções que implementam operações em strings (strings de caracteres e strings de bytes) em sua biblioteca padrão . Várias operações, como cópia, concatenação , tokenização e pesquisa são suportadas. Para cadeias de caracteres, a biblioteca padrão usa a convenção de que as cadeias têm terminação nula : uma cadeia de n caracteres é representada como uma matriz de n + 1 elementos, o último dos quais é um NUL
caractere (com valor numérico 0).
O único suporte para strings na linguagem de programação apropriada é que o compilador traduz constantes de string entre aspas em strings terminadas em nulo.
Definições
Uma string é definida como uma sequência contígua de unidades de código terminadas pela primeira unidade de código zero (freqüentemente chamada de unidade de código NUL ). Isso significa que uma string não pode conter a unidade de código zero, pois a primeira vista marca o final da string. O comprimento de uma string é o número de unidades de código antes da unidade de código zero. A memória ocupada por uma string é sempre uma unidade de código a mais do que o comprimento, pois é necessário espaço para armazenar o terminador zero.
Geralmente, o termo string significa uma string em que a unidade de código é do tipo char
, que tem exatamente 8 bits em todas as máquinas modernas. C90 define cadeias largas que usam uma unidade de código do tipo wchar_t
, que é de 16 ou 32 bits em máquinas modernas. Isso foi planejado para Unicode, mas é cada vez mais comum usar UTF-8 em strings normais para Unicode.
Strings são passados para funções passando um ponteiro para a primeira unidade de código. Visto que char*
e wchar_t*
são tipos diferentes, as funções que processam cadeias de caracteres largas são diferentes daquelas que processam cadeias de caracteres normais e têm nomes diferentes.
Literais de string ( "text"
no código-fonte C) são convertidos em matrizes durante a compilação. O resultado é uma matriz de unidades de código contendo todos os caracteres mais uma unidade de código zero à direita. Em C90 L"text"
produz uma corda larga. Um literal de string pode conter a unidade de código zero (uma maneira é colocá- \0
lo na fonte), mas isso fará com que a string termine nesse ponto. O resto do literal será colocado na memória (com outra unidade de código zero adicionada ao final), mas é impossível saber se essas unidades de código foram traduzidas do literal de string, portanto, esse código-fonte não é um literal de string.
Codificações de caracteres
Cada string termina na primeira ocorrência da unidade de código zero do tipo apropriado ( char
ou wchar_t
). Consequentemente, uma string de bytes ( char*
) pode conter caracteres não NUL em ASCII ou qualquer extensão ASCII , mas não caracteres em codificações como UTF-16 (mesmo que uma unidade de código de 16 bits possa ser diferente de zero, seu byte alto ou baixo pode ser zero). As codificações que podem ser armazenadas em strings largas são definidas pela largura de wchar_t
. Na maioria das implementações, wchar_t
tem pelo menos 16 bits e, portanto, todas as codificações de 16 bits, como UCS-2 , podem ser armazenadas. Se wchar_t
for de 32 bits, as codificações de 32 bits, como UTF-32 , podem ser armazenadas. (O padrão requer um "tipo que contém qualquer caractere largo", que no Windows não é mais verdadeiro, pois o UCS-2 para o UTF-16 muda.) C ++ 11 e C11 adicionam dois tipos com larguras explícitas char16_t
e char32_t
.
Codificações de largura variável podem ser usadas em strings de byte e strings largas. O comprimento da string e os deslocamentos são medidos em bytes ou wchar_t
, não em "caracteres", o que pode ser confuso para programadores iniciantes. UTF-8 e Shift JIS são freqüentemente usados em strings de bytes C, enquanto UTF-16 é freqüentemente usado em strings C largas quando wchar_t
tem 16 bits. Truncar strings com caracteres de comprimento variável usando funções como strncpy
pode produzir sequências inválidas no final da string. Isso pode ser inseguro se as partes truncadas forem interpretadas por um código que presuma que a entrada é válida.
O suporte para literais Unicode, como char foo[512] = "φωωβαρ";
(UTF-8) ou wchar_t foo[512] = L"φωωβαρ";
(UTF-16 ou UTF-32, depende de wchar_t
) é definido pela implementação e pode exigir que o código-fonte esteja na mesma codificação, especialmente para char
onde os compiladores podem apenas copiar o que estiver entre as aspas. Alguns compiladores ou editores exigirão a inserção de todos os caracteres não ASCII como \xNN
sequências para cada byte de UTF-8 e / ou \uNNNN
para cada palavra de UTF-16. Desde C11 (e C ++ 11), uma nova char foo[512] = u8"φωωβαρ";
sintaxe literal está disponível que garante UTF-8 para um literal de bytestring.
Visão geral das funções
A maioria das funções que operam em strings C são declaradas no string.h
cabeçalho ( cstring
em C ++), enquanto funções que operam em strings C são declaradas no wchar.h
cabeçalho ( cwchar
em C ++). Esses cabeçalhos também contêm declarações de funções usadas para manipular buffers de memória; o nome é, portanto, um nome impróprio.
As funções declaradas em string.h
são extremamente populares, pois, como parte da biblioteca padrão C , têm a garantia de funcionar em qualquer plataforma que suporte C. No entanto, existem alguns problemas de segurança com essas funções, como estouros de buffer em potencial quando não usadas com cuidado e adequadamente , fazendo com que os programadores prefiram variantes mais seguras e possivelmente menos portáveis, das quais algumas populares estão listadas abaixo. Algumas dessas funções também violam constância ao aceitar um const
ponteiro de string e retornar um não- const
ponteiro dentro da string. Para corrigir isso, alguns foram separados em duas funções sobrecarregadas na versão C ++ da biblioteca padrão.
Na documentação histórica, o termo "caractere" era frequentemente usado em vez de "byte" para strings C, o que leva muitos a acreditar que essas funções de alguma forma não funcionam para UTF-8 . Na verdade, todos os comprimentos são definidos em bytes e isso é verdade em todas as implementações, e essas funções funcionam tão bem com UTF-8 quanto com codificações de byte único. A documentação do BSD foi corrigida para deixar isso claro, mas a documentação do POSIX, Linux e Windows ainda usa "caractere" em muitos lugares onde "byte" ou "wchar_t" é o termo correto.
As funções para lidar com buffers de memória podem processar sequências de bytes que incluem bytes nulos como parte dos dados. Os nomes dessas funções geralmente começam com mem
, em oposição ao str
prefixo.
Constantes e tipos
Nome | Notas |
---|---|
NULL |
Expansão da macro para a constante de ponteiro nula ; ou seja, uma constante que representa um valor de ponteiro que é garantido não ser um endereço válido de um objeto na memória. |
wchar_t
|
Tipo usado para uma unidade de código em cadeias largas, geralmente um valor de 16 bits ou 32 bits sem sinal. Nenhuma interpretação específica é especificada para essas unidades de código; o padrão C requer apenas que wchar_t seja largo o suficiente para conter o conjunto de caracteres mais amplo entre as localidades do sistema com suporte . Teoricamente, wchar_t pode ter o mesmo tamanho que char e, portanto, não é capaz de conter unidades de código UTF-32 ou UTF-16 . |
wint_t
|
Tipo inteiro que pode conter qualquer valor de wchar_t, bem como o valor da macro WEOF. Este tipo não é alterado por promoções integrais. Normalmente, um valor com sinal de 32 bits. |
mbstate_t
|
Contém todas as informações sobre o estado de conversão necessário de uma chamada para uma função para a outra. |
Funções
String de byte |
Corda larga |
Descrição | |
---|---|---|---|
Manipulação de cordas |
strcpy
|
wcscpy
|
Copia uma string para outra |
strncpy
|
wcsncpy
|
Grava exatamente n bytes, copiando da fonte ou adicionando nulos | |
strcat
|
wcscat
|
Acrescenta uma string a outra | |
strncat
|
wcsncat
|
Acrescenta não mais do que n bytes de uma string para outra | |
strxfrm
|
wcsxfrm
|
Transforma uma string de acordo com a localidade atual | |
Exame de cordas |
strlen
|
wcslen
|
Retorna o comprimento da string |
strcmp
|
wcscmp
|
Compara duas strings ( comparação de três vias ) | |
strncmp
|
wcsncmp
|
Compara um número específico de bytes em duas strings | |
strcoll
|
wcscoll
|
Compara duas strings de acordo com a localidade atual | |
strchr
|
wcschr
|
Encontra a primeira ocorrência de um byte em uma string | |
strrchr
|
wcsrchr
|
Encontra a última ocorrência de um byte em uma string | |
strspn
|
wcsspn
|
Retorna o número de bytes iniciais em uma string que estão em uma segunda string | |
strcspn
|
wcscspn
|
Retorna o número de bytes iniciais em uma string que não estão em uma segunda string | |
strpbrk
|
wcspbrk
|
Encontra em uma string a primeira ocorrência de um byte em um conjunto | |
strstr
|
wcsstr
|
Encontra a primeira ocorrência de uma substring em uma string | |
strtok
|
wcstok
|
Divide uma string em fichas | |
Diversos |
strerror
|
N / D | Retorna uma string contendo uma mensagem derivada de um código de erro |
Manipulação de memória |
memset
|
wmemset
|
Preenche um buffer com um byte repetido |
memcpy
|
wmemcpy
|
Copia um buffer para outro | |
memmove
|
wmemmove
|
Copia um buffer para outro, possivelmente sobrepondo, buffer | |
memcmp
|
wmemcmp
|
Compara dois buffers (comparação de três vias) | |
memchr
|
wmemchr
|
Encontra a primeira ocorrência de um byte em um buffer | |
|
Funções multibyte
Nome | Descrição |
---|---|
mblen
|
Retorna o número de bytes no próximo caractere multibyte |
mbtowc
|
Converte o próximo caractere multibyte em um caractere largo |
wctomb
|
Converte um caractere largo em sua representação multibyte |
mbstowcs
|
Converte uma string multibyte em uma string larga |
wcstombs
|
Converte uma string larga em uma string multibyte |
btowc
|
Converta um caractere de byte único em um caractere largo, se possível |
wctob
|
Converta um caractere largo em um caractere de byte único, se possível |
mbsinit
|
Verifica se um objeto de estado representa o estado inicial |
mbrlen
|
Retorna o número de bytes no próximo caractere multibyte, determinado estado |
mbrtowc
|
Converte o próximo caractere multibyte em um caractere largo, determinado estado |
wcrtomb
|
Converte um caractere largo em sua representação multibyte, determinado estado |
mbsrtowcs
|
Converte uma string multibyte em uma string larga, determinado estado |
wcsrtombs
|
Converte uma string larga em uma string multibyte, dado o estado |
Todas essas funções levam um ponteiro para um mbstate_tobjeto que o chamador deve manter. Isso foi originalmente planejado para rastrear os estados de mudança noMBcodificações, mas as modernas, como UTF-8, não precisam disso. No entanto, essas funções foram projetadas no pressuposto de que obanheirocodificação não é uma codificação de largura variável e, portanto, foi projetada para lidar com exatamente umwchar_tpor vez, passando-o por valor em vez de usar um ponteiro de string. Como UTF-16 é uma codificação de largura variável, ombstate_t foi reutilizado para rastrear pares substitutos na codificação ampla, embora o chamador ainda deva detectar e chamar mbtowc duas vezes para um único personagem.
Conversões numéricas
String de byte |
Corda larga |
Descrição |
---|---|---|
atof
|
N / D | converte uma string em um valor de ponto flutuante ('atof' significa 'ASCII para flutuar') |
atoi atol atoll
|
N / D | converte uma string em um inteiro ( C99 ) ('atoi' significa 'ASCII para inteiro') |
strtof ( C99 ) strtod strtold ( C99 )
|
wcstof ( C99 ) wcstod wcstold ( C99 )
|
converte uma string em um valor de ponto flutuante |
strtol strtoll
|
wcstol wcstoll
|
converte uma string em um inteiro assinado |
strtoul strtoull
|
wcstoul wcstoull
|
converte uma string em um inteiro sem sinal |
|
A biblioteca padrão C contém várias funções para conversões numéricas. As funções que lidam com cadeias de bytes são definidas no stdlib.h
cabeçalho ( cstdlib
cabeçalho em C ++). As funções que lidam com strings largas são definidas no wchar.h
cabeçalho ( cwchar
cabeçalho em C ++).
As strtoxxx
funções não são const-corretas , pois aceitam um const
ponteiro de string e retornam um não- const
ponteiro dentro da string.
Além disso, desde a Emenda Normativa 1 (C95), as atoxx
funções são consideradas subsumidas por strtoxxx
funções, razão pela qual nem C95 nem qualquer padrão posterior fornece versões de caracteres amplos dessas funções. O argumento contra atoxx
é que eles não diferenciam entre um erro e a 0
.
Extensões populares
Nome | Plataforma | Descrição |
---|---|---|
bzero
|
POSIX , BSD | Preenche um buffer com zero bytes, obsoleto por memset
|
memccpy
|
SVID , POSIX | copia até um número especificado de bytes entre duas áreas de memória, que não devem se sobrepor, parando quando um determinado byte é encontrado. |
mempcpy
|
GNU | uma variante de memcpy retornar um ponteiro para o byte após o último byte escrito
|
strcasecmp
|
POSIX, BSD | versões que não diferenciam maiúsculas de minúsculas de strcmp
|
strcat_s
|
janelas | uma variante strcat disso verifica o tamanho do buffer de destino antes de copiar
|
strcpy_s
|
janelas | uma variante strcpy disso verifica o tamanho do buffer de destino antes de copiar
|
strdup
|
POSIX | aloca e duplica uma string |
strerror_r
|
POSIX 1, GNU | uma variante strerror disso é thread-safe. A versão GNU é incompatível com a versão POSIX.
|
stricmp
|
janelas | versões que não diferenciam maiúsculas de minúsculas de strcmp
|
strlcpy
|
BSD, Solaris | uma variante strcpy disso trunca o resultado para caber no buffer de destino
|
strlcat
|
BSD, Solaris | uma variante strcat disso trunca o resultado para caber no buffer de destino
|
strsignal
|
POSIX: 2008 | retorna a representação de string de um código de sinal . Não é seguro para thread. |
strtok_r
|
POSIX | uma variante strtok disso é thread-safe
|
Replacements
Apesar da necessidade bem estabelecida de substituir strcat
e strcpy
com funções que não permitem buffer overflows, nenhum padrão aceito surgiu. Em parte, isso se deve à crença equivocada de muitos programadores C de que strncat
e strncpy
têm o comportamento desejado; no entanto, nenhuma das funções foi projetada para isso (destinavam-se a manipular buffers de string de tamanho fixo com preenchimento nulo, um formato de dados menos comumente usado em software moderno), e o comportamento e os argumentos não são intuitivos e muitas vezes escritos incorretamente, mesmo por especialistas programadores.
A substituição mais popular são as funções strlcat
e strlcpy
, que apareceram no OpenBSD 2.4 em dezembro de 1998. Essas funções sempre gravam um NUL no buffer de destino, truncando o resultado se necessário, e retornam o tamanho do buffer que seria necessário, o que permite a detecção do truncamento e fornece um tamanho para a criação de um novo buffer que não será truncado. Eles foram criticados com base em serem supostamente ineficientes, encorajando o uso de strings C (em vez de alguma forma alternativa superior de string) e ocultando outros erros potenciais. Consequentemente, eles não foram incluídos na biblioteca GNU C (usada por software no Linux), embora sejam implementados nas bibliotecas C para OpenBSD, FreeBSD , NetBSD , Solaris , OS X e QNX , bem como em bibliotecas C alternativas para Linux, como o musl introduzido em 2011. A falta de suporte à biblioteca GNU C não impediu vários autores de software de usá-lo e empacotar um substituto, entre outros SDL , GLib , ffmpeg , rsync e até mesmo internamente no kernel Linux . Implementações de código aberto para essas funções estão disponíveis.
Às vezes, memcpy
ou memmove
são usados, pois podem ser mais eficientes do strcpy
que porque não verificam repetidamente o NUL (isso é menos verdadeiro nos processadores modernos). Como eles precisam de um comprimento de buffer como parâmetro, a configuração correta desse parâmetro pode evitar estouros de buffer.
Como parte de seu Ciclo de Vida de Desenvolvimento de Segurança de 2004 , a Microsoft introduziu uma família de funções "seguras" incluindo strcpy_s
e strcat_s
(junto com muitas outras). Essas funções foram padronizadas com algumas pequenas alterações como parte do C11 opcional (Anexo K) proposto pela ISO / IEC WDTR 24731. Essas funções executam várias verificações, incluindo se a sequência é muito longa para caber no buffer. Se as verificações falharem, uma função "manipulador de restrição de tempo de execução" especificada pelo usuário é chamada, o que geralmente aborta o programa. Algumas funções executam operações destrutivas antes de chamar o manipulador de restrição de tempo de execução; por exemplo, strcat_s
define o destino para a string vazia, o que pode dificultar a recuperação de condições de erro ou depurá-las. Essas funções atraíram muitas críticas porque inicialmente eram implementadas apenas no Windows e, ao mesmo tempo, mensagens de alerta começaram a ser produzidas pelo Microsoft Visual C ++ sugerindo aos programadores que usassem essas funções em vez das padrão. Isso foi especulado por alguns como uma tentativa da Microsoft de prender os desenvolvedores em sua plataforma. Embora implementações de código aberto dessas funções estejam disponíveis, essas funções não estão presentes em bibliotecas C Unix comuns. A experiência com essas funções tem mostrado problemas significativos com sua adoção e erros no uso, então a remoção do Anexo K é proposta para a próxima revisão do padrão C. O uso de memset_s
também foi sugerido como uma forma de evitar otimizações indesejadas do compilador.
Veja também
- Sintaxe C § Strings - sintaxe do código-fonte, incluindo sequências de escape de barra invertida
- Funções de string
Notas
Referências
links externos
- Memcpy rápido em C , vários exemplos de codificação C para direcionar diferentes tipos de arquiteturas de instrução de CPU