Qual é o tipo de literais de string em C e C ++?

Qual é o tipo de string literal em C? É char * ou const char * ou const char * const ?

E quanto ao C ++?

Em C, o tipo de string literal é um char[] – não é const acordo com o tipo, mas é um comportamento indefinido para modificar o conteúdo. Além disso, dois literais de string diferentes que possuem o mesmo conteúdo (ou o suficiente do mesmo conteúdo) podem ou não compartilhar os mesmos elementos da matriz.

Do padrão C99 6.4.5 / 5 “String Literais – Semântica”:

Na fase de tradução 7, um byte ou código de valor zero é anexado a cada seqüência de caracteres multibyte que resulta de uma literal de cadeia de caracteres ou literais. A sequência de caracteres multibyte é então usada para inicializar uma matriz de duração e comprimento de armazenamento estáticos apenas o suficiente para conter a sequência. Para literais de cadeia de caracteres, os elementos da matriz têm o tipo char e são inicializados com os bytes individuais da seqüência de caracteres multibyte; para literais de cadeia larga, os elementos da matriz têm o tipo wchar_t e são inicializados com a sequência de caracteres largos …

Não é especificado se essas matrizes são distintas, desde que seus elementos tenham os valores apropriados. Se o programa tentar modificar essa matriz, o comportamento é indefinido.

Em C ++, “Um literal de string ordinária tem o tipo ‘array de n const char ‘” (de 2.13.4 / 1 “String literals”). Mas há um caso especial no padrão C ++ que faz com que o ponteiro para literais de string seja facilmente convertido em pointers não-qualificados para const (4.2 / 2 “conversão de array para ponteiro”):

Um literal de string (2.13.4) que não é um literal de string larga pode ser convertido em um rvalue do tipo “pointer to char”; um literal de cadeia larga pode ser convertido em um rvalue do tipo “ponteiro para wchar_t”.

Como uma nota lateral – como os arrays em C / C ++ são tão facilmente convertidos em pointers, um literal de string pode ser usado em um contexto de ponteiro, como qualquer array em C / C ++.


Editorialização adicional: o que segue é na maior parte especulação da minha parte sobre a lógica das escolhas feitas pelos padrões C e C ++ em relação aos tipos literais de string. Então pegue com um grão de sal (mas por favor, comente se você tiver correções ou detalhes adicionais):

Eu acho que o padrão C escolheu fazer tipos non const constantes de string porque havia (e é) tanto código que espera poder usar pointers não qualificados para const que apontam para literais. Quando o qualificador const foi adicionado (o que, se não me engano, foi feito em torno do tempo de padronização ANSI, mas muito depois de K & R C ter acumulado uma tonelada de código existente) se eles fizessem pointers para literais de string somente passíveis de serem atribuídos Para os tipos char const* sem um casting, quase todos os programas existentes precisariam ser alterados. Não é uma boa maneira de obter um padrão aceito …

Acredito que a mudança para C ++ que os literais de strings são const é feita principalmente para suportar a possibilidade de uma string literal corresponder de forma mais apropriada a uma sobrecarga que recebe um argumento ” char const* “. Eu acho que havia também o desejo de fechar um buraco no sistema de tipos, mas o buraco foi amplamente aberto pelo caso especial em conversões de array para ponteiro.

O Anexo D do padrão indica que a “conversão implícita de qualificação de const para não-constante para literais de string (4.2) foi preterida”, mas acho que muito código ainda quebraria, que demorará muito tempo até que os implementadores do compilador ou o o comitê de padrões está disposto a realmente puxar o plugue (a menos que alguma outra técnica inteligente possa ser inventada – mas então o buraco estaria de volta, não seria?).

O literal da string AC tem o tipo char [n] onde n é igual ao número de caracteres + 1 para considerar o zero implícito no final da string.

A matriz será alocada estaticamente; não é const , mas modificá-lo é um comportamento indefinido.

Se tiver o tipo de ponteiro char * ou o tipo incompleto char [] , sizeof não funcionará como esperado.

Fazer string literals const é uma linguagem C ++ e não faz parte de nenhum padrão C.

Eles costumavam ser do tipo char[] . Agora eles são do tipo const char[] .

Por várias razões históricas, os literais de string sempre foram do tipo char[] em C.

Logo no início (no C90), foi afirmado que modificar um literal de string invoca um comportamento indefinido.

Eles não proibiram tais modificações, nem fizeram const char[] literais que teriam feito mais sentido. Isto foi por motivos de compatibilidade com versões anteriores com o código antigo. Alguns sistemas operacionais antigos (principalmente o DOS) não protestavam se você modificava literais de string, então havia bastante código ao redor.

C ainda tem esse defeito hoje, mesmo no mais recente padrão C.

C ++ herdou o mesmo defeito de C, mas em padrões posteriores de C ++, eles finalmente fizeram const (literalmente obsoletos em C ++ 03, finalmente corrigidos em C ++ 11).