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 const
elemento seja o mesmo que com um ponteiro const
.
const int *foo,*bar;
que declararia ambos foo
e bar
ser int const *
, mas int const *foo, *bar
declararia foo
ser um int const *
e bar
ser 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 bar
faria bar
? Faça as duas coisas const
e 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 *foo
indica 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 i
um número inteiro no intervalo, [0, 10)
ie [0, 9]
) fará primeiro a desreferência foo
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 um int
(consulte ideone.com/jgjIjR ). Mas typedef
torna 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;
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 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 i1
e i2
pontos, mas não pode alterar o valor para o qual eles apontam.
Este:
int *const i3 = (int*) 0x12345678;
define um const
ponteiro para um número inteiro e inicializa-o para apontar para o local da memória 12345678. Você pode alterar o int
valor no endereço 12345678, mas não pode alterar o endereço para o qual i3
aponta.
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 " foo
pontos ( *
) para um int
que não pode ser alterado ( const
)".
Para o programador, isso significa "Não alterarei o valor do que foo
aponta para".
*foo = 123;
ou foo[0] = 123;
seria inválido.foo = &bar;
é permitido.int *const foo;
Significa " foo
nã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 foo
se refere a".
*foo = 123;
ou foo[0] = 123;
é permitido.foo = &bar;
seria inválido.const int *const foo;
Significa " foo
não é possível alterar ( const
) e aponta ( *
) para um int
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 que foo
se 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 *var
ou 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 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 *
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 int
variável, mas que essa variável é const
para esse ponteiro específico.
Por exemplo:
int var = 10;
int const * _p = &var;
O código acima compila perfeitamente. _p
aponta para uma const
variável, embora var
ela 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 a
ponteiro constante para a variável constante do tipo char.