O que esse erro significa? Eu não posso resolver isso de forma alguma.
aviso: conversão descontinuada da constante de string para 'char *' [-Wwrite-strings]
programming
arduino-ide
c
Federico Corazza
fonte
fonte
Respostas:
Como é meu costume, vou fornecer um pouco de informações técnicas básicas sobre os porquês e os motivos desse erro.
Vou inspecionar quatro maneiras diferentes de inicializar cadeias C e ver quais são as diferenças entre elas. Estas são as quatro maneiras em questão:
Agora, vou querer mudar a terceira letra "i" para "o" para torná-la "Thos is some text". Isso poderia, em todos os casos (você pensaria), ser alcançado por:
Agora vamos ver o que cada maneira de declarar a string faz e como essa
text[2] = 'o';
declaração afetaria as coisas.Primeiro a forma mais comumente visto:
char *text = "This is some text";
. O que isso significa literalmente? Bem, em C, significa literalmente "Crie uma variável chamadatext
que é um ponteiro de leitura-gravação para esta cadeia de caracteres literal que é mantida no espaço somente leitura (código)". Se você tiver a opção-Wwrite-strings
ativada, receberá um aviso, como visto na pergunta acima.Basicamente, isso significa "Aviso: você tentou fazer uma variável que seja de leitura / gravação apontar para uma área na qual não é possível gravar". Se você tentar definir o terceiro caractere como "o", na verdade você tentaria gravar em uma área somente leitura e as coisas não serão boas. Em um PC tradicional com Linux, resulta em:
Agora o segundo:
char text[] = "This is some text";
. Literalmente, em C, isso significa "Crie uma matriz do tipo" char "e inicialize-a com os dados" Isso é algum texto \ 0 ". O tamanho da matriz será grande o suficiente para armazenar os dados". Então, na verdade, ele aloca RAM e copia o valor "Isso é algum texto \ 0" para ele em tempo de execução. Sem avisos, sem erros, perfeitamente válidos. E a maneira certa de fazer isso, se você quiser editar os dados . Vamos tentar executar o comandotext[2] = 'o'
:Funcionou perfeitamente. Boa.
Agora, a terceira via:
const char *text = "This is some text";
. Novamente, o significado literal: "Crie uma variável chamada" texto "que é um ponteiro somente leitura para esses dados na memória somente leitura.". Observe que agora o ponteiro e os dados são somente leitura. Sem erros, sem avisos. O que acontece se tentarmos executar nosso comando de teste? Bem, nós não podemos. O compilador agora é inteligente e sabe que estamos tentando fazer algo ruim:Nem compilará. Agora, tentar gravar na memória somente leitura está protegido, porque informamos ao compilador que nosso ponteiro é a memória somente leitura. Obviamente, ele não precisa apontar para a memória somente leitura, mas se você apontar para a memória de leitura e gravação (RAM), a memória ainda estará protegida contra gravação pelo compilador.
Finalmente, a última forma:
const char text[] = "This is some text";
. Novamente, como antes,[]
ele aloca uma matriz na RAM e copia os dados para ela. No entanto, agora essa é uma matriz somente leitura. Você não pode gravar porque o ponteiro está marcado comoconst
. Tentar escrever nele resulta em:Portanto, um rápido resumo de onde estamos:
Este formulário é completamente inválido e deve ser evitado a todo custo. Abre a porta para todo tipo de coisa ruim acontecendo:
Este formulário é o formulário correto se você deseja tornar os dados editáveis:
Este formulário é o formulário correto se você deseja seqüências de caracteres que não serão editadas:
Este formulário parece um desperdício de RAM, mas tem seus usos. Melhor esquecer por enquanto.
fonte
PROGMEM
,PSTR()
ouF()
. Portanto,const char text[]
não usa mais RAM queconst char *text
.(const char *)(...)
elenco simples . Não há efeito real se a placa não precisar, mas uma grande economia se você portar seu código para uma placa que precise.Para elaborar a excelente resposta de Makenko, há uma boa razão pela qual o compilador avisa sobre isso. Vamos fazer um esboço de teste:
Temos duas variáveis aqui, foo e bar. Modifico um dos itens em setup (), mas veja qual é o resultado:
Eles tanto tem mudado!
De fato, se olharmos para os avisos, vemos:
O compilador sabe que isso é desonesto, e está certo! A razão para isso é que o compilador (razoavelmente) espera que as constantes da string não sejam alteradas (uma vez que são constantes). Portanto, se você se referir à constante da cadeia de caracteres
"This is some text"
várias vezes no seu código, é permitido alocar a mesma memória para todos eles. Agora, se você modificar um, você modifica todos eles!fonte
*foo
e o*bar
uso de diferentes "constantes" de string impediriam que isso acontecesse? Além disso, como isso é diferente de não colocar nenhuma string, comochar *foo;
:?new
, comstrcpy
edelete
).Pare de tentar passar uma constante de cadeia de caracteres em que uma função recebe um
char*
ou altere a função para que ele aceite umconst char*
.Sequências como "sequência aleatória" são constantes.
fonte
Exemplo:
Atenção:
A função
foo
espera um caractere * (que, portanto, pode ser modificado), mas você está passando uma string literal, que não deve ser modificada.O compilador está avisando para não fazer isso. Sendo preterido, pode passar de um aviso para um erro em uma versão futura do compilador.
Solução: Faça foo tomar um const char *:
As versões mais antigas do C (e C ++) permitem escrever código como no meu exemplo acima. Você pode criar uma função (como
foo
) que imprime algo que você transmite a ela e depois transmitir uma string literal (por exemplofoo ("Hi there!");
) .No entanto, uma função que assume
char *
como argumento pode modificar seu argumento (Hi there!
por exemplo, modificar neste caso).Você pode ter escrito, por exemplo:
Infelizmente, passando um literal, você agora modificou esse literal para que "Olá!" agora é "adeus", o que não é bom. De fato, se você copiou uma string mais longa, pode sobrescrever outras variáveis. Ou, em algumas implementações, você receberá uma violação de acesso porque "Olá!" pode ter sido colocado na RAM somente leitura (protegida).
Portanto, os compiladores-escritores estão gradualmente descontinuando esse uso, de modo que as funções às quais você passa um literal devem declarar esse argumento como
const
.fonte
can not
ser modificado?Eu tenho este erro de compilação:
Substitua esta linha:
#define TIME_HEADER "T" // Header tag for serial time sync message
com esta linha:
#define TIME_HEADER 'T' // Header tag for serial time sync message
e compilação vai bem.
fonte