A primeira coisa à esquerda da "const" é o que é constante. Se "const" é a coisa mais distante à esquerda, a primeira coisa à direita é a constante.
Cupcake
4
Como uma dica amigável, nunca esqueça que o cdecl é uma coisa.
Braden Best
Há um outro const char * que é o tipo de retorno de exceção :: what ()
Zhang
Respostas:
363
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
constchar*const
que é um ponteiro constante para um caractere constante (para que nada possa ser alterado).
Nota:
Os dois seguintes formulários são equivalentes:
constchar*
e
charconst*
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:
charconst
sobre
constchar
(com ou sem ponteiro) para que o posicionamento do constelemento seja o mesmo que com um ponteiro const.
Vale a pena observar o que acontece se várias variáveis forem especificadas na mesma declaração? Eu acredito 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.
precisa
1
@ supercat 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 ...
gx_
@gx_: Então eu estava errado - minha incerteza foi por que sugeri que seria útil dizer quais são as regras. O que 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.
supercat
3
@ supercat (oh, somente C, desculpe pelo link do código C ++, cheguei aqui de uma pergunta em C ++) É tudo sobre a sintaxe da declaração C , com uma parte do tipo ("pura") seguida por um declarador . Em " 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).
gx_ 28/08
@supercat E quanto a "um ponteiro para uma matriz de ponteiros para inteiros" (Eu não sei Pascal, não tenho certeza sobre a [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 ).
gx_
102
Para evitar confusão, sempre anexe o qualificador const.
Por quê? "Para evitar confusão" não explica qual é a confusão para mim.
Andrew Weir
14
@ Andrew: Eu estava sugerindo consistência e, portanto, legibilidade. Escrever todos os qualificadores de tipo para que eles modifiquem o que está à esquerda, sempre , é o que eu uso.
Diapir #
1
Na verdade, é a melhor resposta sobre o assunto que encontrei no SO
Trap
8
Como padrão de código, raramente encontrei esse estilo e, portanto, provavelmente não o adotarei. No entanto, como uma ferramenta de aprendizado, essa resposta foi muito útil! (Então eu acho muito ruim este não é o estilo mais comum.)
natevw
8
@Alla: 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.
Diapr /
44
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:
intconst*i1;constint*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".
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 .
"char * const x se refere ao ponteiro de caractere que é constante, mas o local que está apontando pode ser alterado." Errado. O valor no local pode ser alterado e não o próprio local.
PleaseHelp
3
O primeiro é um erro de sintaxe. Talvez você quis dizer a diferença entre
constchar* mychar
e
char*const mychar
Nesse caso, o primeiro é um ponteiro para dados que não podem ser alterados, e o segundo é um ponteiro que sempre apontará para o mesmo endereço.
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:
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";
(Seria muito melhor se a essência da resposta não estivesse escondida atrás de um link, com o texto aqui nem mesmo citando, ou pelo menos se referindo a qualquer uma de suas especificidades, além de um genérico "conforme a regra".)
Sz.
@Sz. Você tem alguma confusão específica aqui que eu possa esclarecer? Realmente não há muito depois de conhecer a regra.
PnotNP
1
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.
Seu dois primeiros são na verdade a mesma e seu terceiro é um erro do compilador :)
workmad3
1
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 1char ca2[10]="bbbb";// char array 2char*pca1= ca1;char*pca2= ca2;charconst*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’charconst**ccss=&ccs;// Goodcharconst**ccss1=&csc;// Bad - warning: initialization from incompatible pointer typechar*const*cscs=&csc;// Goodchar*const*cscs1=&ccs;// Bad - warning: initialization from incompatible pointer typechar**const cssc=&pca1;// Goodchar**const cssc1=&ccs;// Bad - warning: initialization from incompatible pointer typechar**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’}
Ponteiro constante : um ponteiro constante pode apontar apenas para uma única variável do respectivo tipo de dados durante todo o programa. Podemos alterar o valor da variável apontada pelo ponteiro. A inicialização deve ser feita durante o próprio período da declaração.
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);return0;}
Ponteiro para um valor const : neste, um ponteiro pode apontar qualquer número de variáveis do tipo respectivo, mas não podemos alterar o valor do objeto apontado pelo ponteiro naquele momento específico.
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;intconst*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*/return0;}
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":
É dependente do compilador? gcc produz para "const char const *" e "const const char *" e "char const const *" o mesmo resultado -> o ponteiro pode apontar para outro local.
precisa
1
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;intconst* _p =&var;
O código acima compila perfeitamente. _paponta para uma constvariável, embora varela mesma não seja constante.
Respostas:
A diferença é que
const char *
é um ponteiro para aconst char
, enquantochar * const
é um ponteiro constante para achar
.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
que é um ponteiro constante para um caractere constante (para que nada possa ser alterado).
Nota:
Os dois seguintes formulários são equivalentes:
e
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:
sobre
(com ou sem ponteiro) para que o posicionamento do
const
elemento seja o mesmo que com um ponteiroconst
.fonte
const int *foo,*bar;
que declararia ambosfoo
ebar
serint const *
, masint const *foo, *bar
declarariafoo
ser umint const *
ebar
serint *
. Eu achotypedef int * intptr; const intptr foo,bar;
que declararia ambas as variáveis comoint * 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
: Bemint *const foo, *const bar;
,. Sintaxe do declarador C ...int const *foo, *volatile bar
fariabar
? Faça as duas coisasconst
evolatile
? 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 seriavar 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*foo
indica umint const
) e*volatile bar
; ler da direita para a esquerda (boa regra para qualificadores de cv )foo
é um ponteiro para uma const int ebar
é 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]
(comi
um número inteiro no intervalo,[0, 10)
ie[0, 9]
) fará primeiro a desreferênciafoo
para 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 umint
(consulte ideone.com/jgjIjR ). Mastypedef
torna mais fácil (consulte ideone.com/O3wb7d ).Para evitar confusão, sempre anexe o qualificador const.
fonte
p
nã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 functionvoid foo(int a) const;
. A possibilidade de declararconst 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:
eles definem ponteiros para um
const int
. Você pode alterar ondei1
ei2
pontos, mas não pode alterar o valor para o qual eles apontam.Este:
define um
const
ponteiro para um número inteiro e inicializa-o para apontar para o local da memória 12345678. Você pode alterar oint
valor no endereço 12345678, mas não pode alterar o endereço para o quali3
aponta.fonte
const * char
é um código C inválido e não faz sentido. Talvez você quisesse perguntar a diferença entre aconst char *
e achar const *
, ou possivelmente a diferença entre aconst char *
e achar * const
?Veja também:
fonte
const char*
é um ponteiro para um personagem constantechar* const
é um ponteiro constante para um personagemconst char* const
é um ponteiro constante para um personagem constantefonte
Regra prática: leia a definição da direita para a esquerda!
const int *foo;
Significa "
foo
pontos (*
) para umint
que não pode ser alterado (const
)".Para o programador, isso significa "Não alterarei o valor do que
foo
aponta para".*foo = 123;
oufoo[0] = 123;
seria inválido.foo = &bar;
é permitido.int *const foo;
Significa "
foo
não é possível alterar (const
) e apontar (*
) para umint
".Para o programador, isso significa "Não alterarei o endereço de memória que
foo
se refere a".*foo = 123;
oufoo[0] = 123;
é permitido.foo = &bar;
seria inválido.const int *const foo;
Significa "
foo
não é possível alterar (const
) e aponta (*
) para umint
que não pode ser alterado (const
)".Para o programador, isso significa "Eu não alterarei o valor do que
foo
aponta, nem alterarei o endereço quefoo
se refere a".*foo = 123;
oufoo[0] = 123;
seria inválido.foo = &bar;
seria inválido.fonte
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 .
fonte
O primeiro é um erro de sintaxe. Talvez você quis dizer a diferença entre
e
Nesse caso, o primeiro é um ponteiro para dados que não podem ser alterados, e o segundo é um ponteiro que sempre apontará para o mesmo endereço.
fonte
Outra regra básica é verificar onde const está :
fonte
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:
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 compilarB)
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";
fonte
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.
fonte
Aqui está uma explicação detalhada com o código
fonte
fonte
Sintaxe:
char *const
vem sob este caso.Sintaxe:
const datatype *var
oudatatype const *var
const char*
vem sob este caso.fonte
char * const e const char *?
const char * p;
// o valor não pode ser alteradochar * const p;
// endereço não pode ser alteradoconst char * const p;
// ambos não podem ser alterados.fonte
O
const
modificador é 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 * const
const char const *
char const * const
char const const *
fonte
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.
fonte
Gostaria de salientar que usar
int const *
(ouconst int *
) não é um ponteiro apontando para umaconst int
variável, mas que essa variável éconst
para esse ponteiro específico.Por exemplo:
O código acima compila perfeitamente.
_p
aponta para umaconst
variável, emboravar
ela mesma não seja constante.fonte
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
você pode ler como: "
a
é variável do tipo ponteiro constante parachar
",você pode ler como: "
a
é um ponteiro para variável constante do tipo char. Espero que isso ajude.Bônus:
Você lerá o
a
ponteiro constante para a variável constante do tipo char.fonte