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?
constse 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 namepontos, e também o caractere em que aponta.
const char* name
Você pode alterar o caractere em que namepontos, 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 nameaponta ( https://msdn.microsoft.com/en-us/library/vstudio/whkd4k6a(v=vs.100).aspx , consulte "Exemplos" ) Nesse caso, o constespecificador 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 constantes do *faz parte da sequência decl-specifier, enquanto o constdepois *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, c2declara c1comoconst char * e c2como 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 namepontos, 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.
namepontos 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 ... namee 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 constcorreção (há alguns guias legais sobre a diferença). Também há char const * nameonde 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 *cnameou cname[n]será avaliada em valores do tipo const char, enquanto *nameou 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.