Яка різниця між:
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
(оскільки постфікс []
пов'язується жорсткіше за префікс *
), потім дереференція цього елемента, нарешті виходить 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 ++, має бути postfix: cf const member member function void foo(int a) const;
. Можливість декларації const int
- це швидше виняток, ніж правило.
const
завжди модифікує те, що знаходиться перед ним (ліворуч від нього), ПРИ ВКЛЮЧЕННЯ, коли це перше, що відбувається в оголошенні типу, де воно змінює річ, що йде після неї (праворуч від неї).
Отже, це двоє:
int const *i1;
const int *i2;
вони визначають покажчики на a 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 призведе до помилки компілятора. її не можна оголосити.
char const * x дорівнює точці 1.
правило: якщо const є з ім'ям var, то вказівник буде постійним, але розташування вказівника може бути змінено , інакше вказівник буде вказувати на постійне місце розташування і вказівник може вказувати на інше місце, але вміст місця вказівки не може бути змінений .
Багато відповідей містять конкретні прийоми, правило великих пальців тощо для розуміння цього конкретного примірника змінної декларації. Але є загальна техніка розуміння будь-якої декларації:
За годинниковою стрілкою / Правило спіралі
А)
const char *a;
Згідно з правилом за годинниковою стрілкою / спіраллю a
є вказівник на характер, який є постійним. Що означає, що символ є постійним, але вказівник може змінюватися. тобто a = "other string";
добре, але a[2] = 'c';
не вдасться компілювати
Б)
char * const a;
Як правило, a
це const вказівник на персонаж. тобто ви можете робити, 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 * const
const char const *
char const * const
char 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
сама по собі не є постійною.
Я пам’ятаю з чеської книги про С: прочитайте декларацію, що ви починаєте зі змінної, та йдіть вліво. Так для
char * const a;
ви можете прочитати як: " a
є змінною постійного вказівника типу на char
",
char const * a;
Ви можете прочитати як: " a
- вказівник на постійну змінну типу char. Сподіваюся, це допоможе.
Бонус:
const char * const a;
Ви прочитаєте як a
постійний вказівник на постійну змінну типу char.