Qual é a diferença entre
char* name
que aponta para uma constante string literal e
const char* name
Qual é a diferença entre
char* name
que aponta para uma constante string literal e
const char* name
Respostas:
char*
é um ponteiro mutável para um caractere / sequência mutável .
const char*
é um ponteiro mutável para um caractere / sequência imutável . Você não pode alterar o conteúdo dos locais para os quais este ponteiro aponta. Além disso, os compiladores são obrigados a fornecer mensagens de erro quando você tenta fazer isso. Pelo mesmo motivo, a conversão de const char *
para char*
foi preterida.
char* const
é um ponteiro imutável (não pode apontar para nenhum outro local), mas o conteúdo do local no qual aponta é mutável .
const char* const
é um ponteiro imutável para um caractere / sequência imutável .
char const *
char *
falha de segmentação durante a execução?
const
se eu quero que o compilador dê erro se eu esqueci e alterei os dados por engano, certo?
char *name
Você pode alterar o caractere em que name
pontos, e também o caractere em que aponta.
const char* name
Você pode alterar o caractere em que name
pontos, mas não pode modificar o caractere em que aponta.
correção: você pode alterar o ponteiro, mas não o caracter para o qual name
aponta ( https://msdn.microsoft.com/en-us/library/vstudio/whkd4k6a(v=vs.100).aspx , consulte "Exemplos" ) Nesse caso, o const
especificador se aplica ao char
, não ao asterisco.
De acordo com a página do MSDN e http://en.cppreference.com/w/cpp/language/declarations , o const
antes do *
faz parte da sequência decl-specifier, enquanto o const
depois *
faz parte do declarador.
Uma sequência do especificador de declaração pode ser seguida por vários declaradores, razão pela qual const char * c1, c2
declara c1
comoconst char *
e c2
como const char
.
EDITAR:
A partir dos comentários, sua pergunta parece estar se perguntando sobre a diferença entre as duas declarações quando o ponteiro aponta para uma string literal.
Nesse caso, você não deve modificar o caractere em que name
pontos, pois isso pode resultar em comportamento indefinido . Literais de seqüência de caracteres podem ser alocados em regiões de memória somente leitura (implementação definida) e um programa do usuário não deve modificá-lo de qualquer maneira. Qualquer tentativa de fazer isso resulta em comportamento indefinido.
Portanto, a única diferença nesse caso (de uso com literais de seqüência de caracteres) é que a segunda declaração oferece uma pequena vantagem. Os compiladores geralmente emitem um aviso caso você tente modificar a string literal no segundo caso.
#include <string.h>
int main()
{
char *str1 = "string Literal";
const char *str2 = "string Literal";
char source[] = "Sample string";
strcpy(str1,source); //No warning or error, just Undefined Behavior
strcpy(str2,source); //Compiler issues a warning
return 0;
}
Resultado:
cc1: avisos sendo tratados como erros
prog.c: Na função 'main':
prog.c: 9: error: passar o argumento 1 de 'strcpy' descarta qualificadores do tipo de destino do ponteiro
Observe que o compilador avisa para o segundo caso, mas não para o primeiro.
name
pontos em ambos os casos. Isso pode resultar em UB.
char mystring[101] = "My sample string";
const char * constcharp = mystring; // (1)
char const * charconstp = mystring; // (2) the same as (1)
char * const charpconst = mystring; // (3)
constcharp++; // ok
charconstp++; // ok
charpconst++; // compile error
constcharp[3] = '\0'; // compile error
charconstp[3] = '\0'; // compile error
charpconst[3] = '\0'; // ok
// String literals
char * lcharp = "My string literal";
const char * lconstcharp = "My string literal";
lcharp[0] = 'X'; // Segmentation fault (crash) during run-time
lconstcharp[0] = 'X'; // compile error
// *not* a string literal
const char astr[101] = "My mutable string";
astr[0] = 'X'; // compile error
((char*)astr)[0] = 'X'; // ok
char *
valor dá falha de segmentação, uma vez que está tentando modificar um literal string (que está presente em memória apenas para leitura)
Em nenhum dos casos, você pode modificar um literal de cadeia de caracteres, independentemente de o ponteiro para esse literal de cadeia ser declarado como char *
ouconst char *
.
No entanto, a diferença é que, se o ponteiro estiver const char *
, o compilador deverá fornecer um diagnóstico se você tentar modificar o valor apontado, mas se o ponteiro estiver char *
, não o fará.
extern ... name
e ter *name = 'X';
. No 'sistema operacional adequado', isso pode falhar, mas em sistemas embarcados, espero que faça algo específico da plataforma / compilador.
CASO 1:
char *str = "Hello";
str[0] = 'M' //Warning may be issued by compiler, and will cause segmentation fault upon running the programme
O conjunto acima define str para apontar para o valor literal "Hello" que é codificado na imagem binária do programa, que é sinalizada como somente leitura na memória, significa que qualquer alteração nesse literal String é ilegal e causaria falhas de segmentação.
CASO 2:
const char *str = "Hello";
str[0] = 'M' //Compile time error
CASO 3:
char str[] = "Hello";
str[0] = 'M'; // legal and change the str = "Mello".
O primeiro você pode realmente mudar, se quiser, o segundo, não. Leia sobre const
correção (há alguns guias legais sobre a diferença). Também há char const * name
onde você não pode refazê-lo.
A questão é qual é a diferença entre
char *name
que aponta para uma constante string literal e
const char *cname
Ou seja, dado
char *name = "foo";
e
const char *cname = "foo";
Não há muita diferença entre os 2 e ambos podem ser vistos como corretos. Devido ao longo legado do código C, os literais de string tiveram um tipo de char[]
, não const char[]
, e há muitos códigos mais antigos que da mesma forma aceitam, em char *
vez deconst char *
, mesmo quando não modificam os argumentos.
A principal diferença dos 2 em geral é que *cname
ou cname[n]
será avaliada em valores do tipo const char
, enquanto *name
ou name[n]
será avaliada em valores do tipo char
, que são valores modificáveis . Um compilador em conformidade é necessário para produzir uma mensagem de diagnóstico se o destino da atribuição não for um valor lificável modificável ; ele não precisa produzir nenhum aviso na atribuição para lvalues do tipo char
:
name[0] = 'x'; // no diagnostics *needed*
cname[0] = 'x'; // a conforming compiler *must* produce a diagnostics message
O compilador não é necessário para interromper a compilação nos dois casos; basta produzir um aviso para a atribuição cname[0]
. O programa resultante não é um programa correto . O comportamento da construção é indefinido . Pode travar ou, pior ainda, pode não travar e pode alterar a string literal na memória.
Na realidade, char* name
não é um ponteiro para uma constante, mas um ponteiro para uma variável. Você pode estar falando sobre essa outra questão.