Qual é a diferença entre:
char * const
e
const char *
Qual é a diferença entre:
char * const
e
const char *
Respostas:
A diferença é que const char *é um ponteiro para a const char, enquanto char * consté um ponteiro constante para a char.
A primeira, o valor apontado não pode ser alterado, mas o ponteiro pode ser. O segundo, o valor apontado pode mudar, mas o ponteiro não pode (semelhante a uma referência).
Há também um
const char * const
que é um ponteiro constante para um caractere constante (para que nada possa ser alterado).
Nota:
Os dois seguintes formulários são equivalentes:
const char *
e
char const *
A razão exata para isso é descrita no padrão C ++, mas é importante observar e evitar a confusão. Conheço vários padrões de codificação que preferem:
char const
sobre
const char
(com ou sem ponteiro) para que o posicionamento do constelemento seja o mesmo que com um ponteiro const.
const int *foo,*bar;que declararia ambos fooe barser int const *, mas int const *foo, *bardeclararia fooser um int const *e barser int *. Eu acho typedef int * intptr; const intptr foo,bar;que declararia ambas as variáveis como int * const; Não conheço nenhuma maneira de usar uma declaração combinada para criar duas variáveis desse tipo sem um typedef.
I believe const int *foo,*bar; would declare both foo and bar to be int const *: Sim. but int const *foo, *bar would declare foo to be a int const * and bar to be int *: Não! Seria exatamente o mesmo que no caso anterior. (Consulte ideone.com/RsaB7n, onde você obtém o mesmo erro para foo e bar). I think typedef int * intptr; const intptr foo,bar; would declare both variables to be int * const: Sim. I don't know any way to use a combined declaration to create two variables of that type without a typedef: Bem int *const foo, *const bar;,. Sintaxe do declarador C ...
int const *foo, *volatile barfaria bar? Faça as duas coisas conste volatile? Eu sinto falta da separação limpa de Pascal de nomes de variáveis declaradas e seus tipos (um ponteiro para uma matriz de ponteiros para números inteiros seria var foo: ^Array[3..4] of ^Integer; `. Isso seria algo engraçado entre parênteses aninhados em C, eu acho.
int const *foo, *volatile bar" a parte do tipo é int const(para antes de *) e os declaradores *foo(a expressão *fooindica um int const) e *volatile bar; ler da direita para a esquerda (boa regra para qualificadores de cv ) fooé um ponteiro para uma const int e baré um ponteiro volátil para uma const int (o ponteiro em si é volátil, o int apontado é [acessado como] const).
[3..4]sintaxe, então vamos dar um array de 10 elementos): int *(*foo)[10];. Ele reflete seu uso (futuro) como uma expressão: *(*foo)[i](com ium número inteiro no intervalo, [0, 10)ie [0, 9]) fará primeiro a desreferência foopara chegar ao array e, em seguida, acessará o elemento no índicei (por causa do sufixo []se liga mais apertados do que prefixo *), em seguida, cancelar a referência desse elemento, finalmente produzindo um int(consulte ideone.com/jgjIjR ). Mas typedeftorna mais fácil (consulte ideone.com/O3wb7d ).
Para evitar confusão, sempre anexe o qualificador const.
int * mutable_pointer_to_mutable_int;
int const * mutable_pointer_to_constant_int;
int *const constant_pointer_to_mutable_int;
int const *const constant_pointer_to_constant_int;
pnão se relaciona com o tipo: (const int *const). Para melhor ou pior (pior, se você me perguntar), o qualificador const, tanto em C quanto em C ++, deve ser postfix: cf const member function void foo(int a) const;. A possibilidade de declarar const inté a exceção e não a regra.
const sempre modifica o que vem antes (à esquerda), EXCETO quando é a primeira coisa em uma declaração de tipo, onde modifica o que vem depois (à direita).
Então, esses dois são os mesmos:
int const *i1;
const int *i2;
eles definem ponteiros para um const int . Você pode alterar onde i1e i2pontos, mas não pode alterar o valor para o qual eles apontam.
Este:
int *const i3 = (int*) 0x12345678;
define um constponteiro para um número inteiro e inicializa-o para apontar para o local da memória 12345678. Você pode alterar o intvalor no endereço 12345678, mas não pode alterar o endereço para o qual i3aponta.
const * charé um código C inválido e não faz sentido. Talvez você quisesse perguntar a diferença entre a const char *e a char const *, ou possivelmente a diferença entre a const char *e achar * const ?
const char*é um ponteiro para um personagem constante
char* consté um ponteiro constante para um personagem
const char* consté um ponteiro constante para um personagem constante
Regra prática: leia a definição da direita para a esquerda!
const int *foo;Significa " foopontos ( *) para um intque não pode ser alterado ( const)".
Para o programador, isso significa "Não alterarei o valor do que fooaponta para".
*foo = 123; ou foo[0] = 123; seria inválido.foo = &bar; é permitido.int *const foo;Significa " foonão é possível alterar ( const) e apontar ( *) para um int".
Para o programador, isso significa "Não alterarei o endereço de memória que foose refere a".
*foo = 123; ou foo[0] = 123; é permitido.foo = &bar; seria inválido.const int *const foo;Significa " foonão é possível alterar ( const) e aponta ( *) para um intque não pode ser alterado ( const)".
Para o programador, isso significa "Eu não alterarei o valor do que fooaponta, nem alterarei o endereço que foose refere a".
*foo = 123; ou foo[0] = 123; seria inválido.foo = &bar; seria inválido.const char * x Aqui X é basicamente um ponteiro de caractere que está apontando para um valor constante
char * const x refere-se ao ponteiro de caractere que é constante, mas o local que está apontando pode ser alterado.
const char * const x é uma combinação de 1 e 2, significa que é um ponteiro de caractere constante que está apontando para um valor constante.
const * char x causará um erro do compilador. não pode ser declarado.
char const * x é igual ao ponto 1.
a regra geral é que, se const estiver com o nome var, o ponteiro será constante, mas o local do apontador poderá ser alterado , caso contrário, o ponteiro apontará para um local constante e o ponteiro poderá apontar para outro local, mas o conteúdo do local do apontador não poderá ser alterado .
Muitas respostas fornecem técnicas específicas, regra geral, etc. para entender essa instância específica da declaração de variáveis. Mas existe uma técnica genérica de entender qualquer declaração:
Regra no sentido horário / espiral
A)
const char *a;
De acordo com a regra no sentido horário / espiral, aé ponteiro para o caractere constante. O que significa que o caractere é constante, mas o ponteiro pode mudar. ou seja, a = "other string";está bem, masa[2] = 'c'; falhará ao compilar
B)
char * const a;
De acordo com a regra, aé um ponteiro constante para um personagem. ou seja, você pode fazer, a[2] = 'c';mas você não pode fazera = "other string";
Presumo que você queira dizer const char * e char * const.
O primeiro, const char *, é um ponteiro para um caractere constante. O ponteiro em si é mutável.
O segundo, char * const é um ponteiro constante para um personagem. O ponteiro não pode mudar, o caractere que ele aponta pode.
E depois há const char * const onde o ponteiro e o caractere não podem mudar.
Aqui está uma explicação detalhada com o código
/*const char * p;
char * const p;
const char * const p;*/ // these are the three conditions,
// const char *p;const char * const p; pointer value cannot be changed
// char * const p; pointer address cannot be changed
// const char * const p; both cannot be changed.
#include<stdio.h>
/*int main()
{
const char * p; // value cannot be changed
char z;
//*p = 'c'; // this will not work
p = &z;
printf(" %c\n",*p);
return 0;
}*/
/*int main()
{
char * const p; // address cannot be changed
char z;
*p = 'c';
//p = &z; // this will not work
printf(" %c\n",*p);
return 0;
}*/
/*int main()
{
const char * const p; // both address and value cannot be changed
char z;
*p = 'c'; // this will not work
p = &z; // this will not work
printf(" %c\n",*p);
return 0;
}*/
// Some more complex constant variable/pointer declaration.
// Observing cases when we get error and warning would help
// understanding it better.
int main(void)
{
char ca1[10]= "aaaa"; // char array 1
char ca2[10]= "bbbb"; // char array 2
char *pca1= ca1;
char *pca2= ca2;
char const *ccs= pca1;
char * const csc= pca2;
ccs[1]='m'; // Bad - error: assignment of read-only location ‘*(ccs + 1u)’
ccs= csc; // Good
csc[1]='n'; // Good
csc= ccs; // Bad - error: assignment of read-only variable ‘csc’
char const **ccss= &ccs; // Good
char const **ccss1= &csc; // Bad - warning: initialization from incompatible pointer type
char * const *cscs= &csc; // Good
char * const *cscs1= &ccs; // Bad - warning: initialization from incompatible pointer type
char ** const cssc= &pca1; // Good
char ** const cssc1= &ccs; // Bad - warning: initialization from incompatible pointer type
char ** const cssc2= &csc; // Bad - warning: initialization discards ‘const’
// qualifier from pointer target type
*ccss[1]= 'x'; // Bad - error: assignment of read-only location ‘**(ccss + 8u)’
*ccss= ccs; // Good
*ccss= csc; // Good
ccss= ccss1; // Good
ccss= cscs; // Bad - warning: assignment from incompatible pointer type
*cscs[1]= 'y'; // Good
*cscs= ccs; // Bad - error: assignment of read-only location ‘*cscs’
*cscs= csc; // Bad - error: assignment of read-only location ‘*cscs’
cscs= cscs1; // Good
cscs= cssc; // Good
*cssc[1]= 'z'; // Good
*cssc= ccs; // Bad - warning: assignment discards ‘const’
// qualifier from pointer target type
*cssc= csc; // Good
*cssc= pca2; // Good
cssc= ccss; // Bad - error: assignment of read-only variable ‘cssc’
cssc= cscs; // Bad - error: assignment of read-only variable ‘cssc’
cssc= cssc1; // Bad - error: assignment of read-only variable ‘cssc’
}
Sintaxe:
datatype *const var;
char *const vem sob este caso.
/*program to illustrate the behaviour of constant pointer */
#include<stdio.h>
int main(){
int a=10;
int *const ptr=&a;
*ptr=100;/* we can change the value of object but we cannot point it to another variable.suppose another variable int b=20; and ptr=&b; gives you error*/
printf("%d",*ptr);
return 0;
}
Sintaxe:
const datatype *varou datatype const *var
const char* vem sob este caso.
/* program to illustrate the behavior of pointer to a constant*/
#include<stdio.h>
int main(){
int a=10,b=20;
int const *ptr=&a;
printf("%d\n",*ptr);
/* *ptr=100 is not possible i.e we cannot change the value of the object pointed by the pointer*/
ptr=&b;
printf("%d",*ptr);
/*we can point it to another object*/
return 0;
}
char * const e const char *?
const char * p; // o valor não pode ser alterado
char * const p; // endereço não pode ser alterado
const char * const p; // ambos não podem ser alterados.
O constmodificador é aplicado ao termo imediatamente à sua esquerda. A única exceção é quando não há nada à sua esquerda, então se aplica ao que está imediatamente à sua direita.
Todas essas são maneiras equivalentes de dizer "ponteiro constante para uma constante char":
const char * constconst char const *char const * constchar const const *Duas regras
If const is between char and *, it will affect the left one.If const is not between char and *, it will affect the nearest one.por exemplo
char const *. This is a pointer points to a constant char.char * const. This is a constant pointer points to a char.Gostaria de salientar que usar int const *(ou const int *) não é um ponteiro apontando para uma const intvariável, mas que essa variável é constpara esse ponteiro específico.
Por exemplo:
int var = 10;
int const * _p = &var;
O código acima compila perfeitamente. _paponta para uma constvariável, embora varela mesma não seja constante.
Lembro-me do livro tcheco sobre C: leia a declaração de que você começa com a variável e vai para a esquerda. Então para
char * const a;
você pode ler como: " aé variável do tipo ponteiro constante para char",
char const * a;
você pode ler como: "a é um ponteiro para variável constante do tipo char. Espero que isso ajude.
Bônus:
const char * const a;
Você lerá o aponteiro constante para a variável constante do tipo char.