Какая разница между:
char * const
и
const char *
Какая разница между:
char * const
и
const char *
Ответы:
Разница в том, что const char *указатель на a const char, а char * constпостоянный указатель на a char.
Во-первых, указанное значение не может быть изменено, но указатель может быть. Во-вторых, значение, на которое указывает указатель, может измениться, но указатель не может (аналогично ссылке).
Также есть
const char * const
который является постоянным указателем на постоянный символ (поэтому ничего нельзя изменить).
Примечание:
Следующие две формы эквивалентны:
const char *
и
char const *
Точная причина этого описана в стандарте C ++, но важно помнить и избегать путаницы. Я знаю несколько стандартов кодирования, которые предпочитают:
char const
над
const char
(с указателем или без него), чтобы размещение constэлемента было таким же, как и с указателем const.
const int *foo,*bar;было бы объявить как fooи barбыть int const *, но int const *foo, *barбыло бы объявить , fooчтобы быть int const *и barбыть int *. Я думаю, typedef int * intptr; const intptr foo,bar;что объявил бы обе переменные int * const; Я не знаю, как использовать комбинированное объявление для создания двух переменных этого типа без typedef.
I believe const int *foo,*bar; would declare both foo and bar to be int const *: Да. but int const *foo, *bar would declare foo to be a int const * and bar to be int *: Нет! Это было бы точно так же, как и в предыдущем случае. (См. Ideone.com/RsaB7n, где вы получаете одинаковую ошибку как для foo, так и для bar). I think typedef int * intptr; const intptr foo,bar; would declare both variables to be int * const: Да. I don't know any way to use a combined declaration to create two variables of that type without a typedef: Ну int *const foo, *const bar;. Синтаксис объявления C ...
int const *foo, *volatile barсделать bar? Сделай и то constи другое volatile? Я скучаю по чистому разделению Паскаля имен объявленных переменных и их типов (указатель на массив указателей на целые числа был бы var foo: ^Array[3..4] of ^Integer; `. Я думаю, это было бы забавной вложенной скобкой в C
int const *foo, *volatile bar" часть типа - это int const(останавливается перед *), а деклараторы *foo(выражение *fooбудет обозначать int const) и *volatile bar; чтение справа налево (хорошее правило для cv-квалификаторов ), fooявляется указателем на const int и barявляется энергозависимым указателем на const int (сам указатель является энергозависимым, на указанный int [обращаются как] const).
[3..4]синтаксисе, поэтому давайте рассмотрим массив из 10 элементов): int *(*foo)[10];. Он отражает его (будущее) использование в качестве выражения: *(*foo)[i](с iцелым числом в диапазоне, [0, 10)т. [0, 9]Е.) Будет сначала разыменовываться, fooчтобы получить массив, затем обращаться к элементу по индексу i(потому что postfix []связывается более сильно, чем префикс *), затем разыменовывается этот элемент, наконец, получая int(см. ideone.com/jgjIjR ). Но typedefделает это проще (см. Ideone.com/O3wb7d ).
Чтобы избежать путаницы, всегда добавляйте 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не относится к типу: (const int *const). К счастью или к худшему (хуже, если вы спросите меня), квалификатор const, как в C, так и в C ++, должен быть постфиксом: cf const функция-член void foo(int a) const;. Возможность объявить const intявляется скорее исключением, чем правилом.
const всегда изменяет то, что стоит перед ним (слева от него), ЗА ИСКЛЮЧЕНИЕМ, когда это первое в объявлении типа, где оно изменяет то, что следует за ним (справа от него).
Итак, эти два одинаковы:
int const *i1;
const int *i2;
они определяют указатели на const int. Вы можете изменить место i1и i2точки, но вы не можете изменить значение, на которое они указывают.
Это:
int *const i3 = (int*) 0x12345678;
определяет constуказатель на целое число и инициализирует его, чтобы он указывал на ячейку памяти 12345678. Вы можете изменить intзначение по адресу 12345678, но вы не можете изменить адрес, на который i3указывает.
const * charявляется недействительным кодом C и не имеет смысла. Возможно, вы хотели спросить разницу между a const char *и a char const *, или, возможно, разницу между a const char *и a char * const?
const char*является указателем на постоянный символ
char* constявляется постоянным указателем на символ
const char* constявляется постоянным указателем на постоянный символ
Правило большого пальца: прочитайте определение справа налево!
const int *foo;Означает « fooуказывает ( *) на то, intчто не может изменить ( const)».
Для программиста это означает: «Я не буду менять значение того, на что fooуказывает».
*foo = 123;или foo[0] = 123;будет недействительным.foo = &bar; позволено.int *const foo;Означает " fooне может изменить ( const) и указывает ( *) на int".
Для программиста это означает: «Я не буду менять адрес памяти, который fooотносится к».
*foo = 123;или foo[0] = 123;разрешено.foo = &bar; будет недействительным.const int *const foo;Означает « fooне может изменить ( const) и указывает ( *) на intчто не может изменить ( const)».
Для программиста это означает: «Я не буду менять значение того, на что fooуказывает, и я не буду менять адрес, который fooссылается».
*foo = 123;или foo[0] = 123;будет недействительным.foo = &bar; будет недействительным.const char * x Здесь X в основном символьный указатель, который указывает на постоянное значение
char * const x относится к символьному указателю, который является постоянным, но местоположение, на которое он указывает, может быть изменено.
const char * const x является комбинацией 1 и 2, означает, что это постоянный символьный указатель, который указывает на постоянное значение.
const * char x вызовет ошибку компилятора. это не может быть объявлено.
символ const * x равен точке 1.
Эмпирическое правило: если const с именем переменной, тогда указатель будет постоянным, но местоположение указателя может быть изменено , иначе указатель будет указывать на постоянное местоположение, а указатель может указывать на другое местоположение, но содержимое указательного места не может быть изменено .
Множество ответов предоставляют конкретные приемы, практическое правило и т. Д., Чтобы понять этот конкретный случай объявления переменной. Но есть общая методика понимания любой декларации:
Правило по часовой стрелке / спираль
A)
const char *a;
Согласно правилу по часовой стрелке / спирали aуказатель на символ является постоянным. Это означает, что символ является постоянным, но указатель может измениться. то a = "other string";есть нормально, но a[2] = 'c';не скомпилируется
B)
char * const a;
Согласно правилу, aэто постоянный указатель на символ. то есть вы можете делать, a[2] = 'c';но не можетеa = "other string";
Я предполагаю, что вы имеете в виду const char * и char * const.
Первый, const char *, является указателем на постоянный символ. Сам указатель является изменяемым.
Второе, char * const - это постоянный указатель на символ. Указатель не может измениться, символ, на который он указывает, может.
И затем есть const char * const, где указатель и символ не могут измениться.
Вот подробное объяснение с кодом
/*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’
}
Синтаксис:
datatype *const var;
char *const подпадает под этот случай.
/*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;
}
Синтаксис:
const datatype *varили datatype const *var
const char* подпадает под этот случай.
/* 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 и const char *?
const char * p; // значение не может быть изменено
char * const p; // адрес не может быть изменен
const char * const p; // оба не могут быть изменены.
constМодификатор применяется к термину сразу слева от нее . Единственное исключение - когда слева ничего нет, тогда это относится к тому, что находится справа справа.
Это все эквивалентные способы сказать «постоянный указатель на постоянную char»:
const char * constconst char const *char const * constchar const const *Два правила
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.например
char const *. This is a pointer points to a constant char.char * const. This is a constant pointer points to a char.Я хотел бы отметить, что использование int const *(или const int *) не о указателе, указывающем на const intпеременную, а о том, что эта переменная предназначена constдля этого конкретного указателя.
Например:
int var = 10;
int const * _p = &var;
Код выше компилируется отлично. _pуказывает на constпеременную, хотя varсама не является постоянной.
Я помню из чешской книги о C: прочитайте декларацию, что вы начинаете с переменной и идете налево. Таким образом, для
char * const a;
Вы можете читать как: « aпеременная типа указатель на постоянную char»,
char const * a;
Вы можете читать как: " aэто указатель на постоянную переменную типа char. Надеюсь, это поможет.
Бонус:
const char * const a;
Вы будете читать как aпостоянный указатель на постоянную переменную типа char.