В чем разница между char * const и const char *?

187

Какая разница между:

char * const 

и

const char *
  • 0
    Возможный дубликат В чем разница между const int *, const int * const и int const *?
  • 5
    Первое, что находится слева от «const» - это то, что постоянно. Если «const» - это самое дальнее слева, то первое, что справа от него, является постоянным.
Показать ещё 1 комментарий
Теги:
pointers
const

17 ответов

281
Лучший ответ

Разница в том, что const char * является указателем на const char, а char * const является указателем константы на char.

Во-первых, указанное значение не может быть изменено, но указатель может быть. Во-вторых, указанное значение может меняться, но указатель не может (похоже на ссылку).

Существует также

const char * const

который является постоянным указателем на константу char (поэтому ничего об этом не может быть изменено).

Примечание:

Следующие две формы эквивалентны:

const char *

и

char const *

Точная причина этого описана в стандарте С++, но важно отметить и избежать путаницы. Я знаю несколько стандартов кодирования, которые предпочитают:

char const

над

const char

(с указателем или без него), так что размещение элемента const совпадает с указателем const.

  • 6
    Стоит ли отмечать, что происходит, если в одной декларации указано несколько переменных? Я верю, что 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.
  • 1
    @supercat 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 ...
Показать ещё 5 комментариев
67

Чтобы избежать путаницы, всегда добавляйте спецификатор 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;
  • 9
    Зачем? «Чтобы избежать путаницы» не объясняет, что такое путаница для меня.
  • 11
    @ Андрей: я намекал на последовательность и, следовательно, удобочитаемость. Писать все классификаторы типов, чтобы они модифицировали то, что слева, всегда то , что я использую.
Показать ещё 11 комментариев
24

const всегда изменяет то, что приходит перед ним (слева от него), ИСКЛЮЧАЕТЕ, когда это первое в объявлении типа, где оно изменяет вещь, которая приходит после него (справа от нее).

Итак, эти два значения:

int const *i1;
const int *i2;

они определяют указатели на a const int. Вы можете изменить точки i1 и i2, но вы не можете изменить значение, на которое они указывают.

Это:

int *const i3 = (int*) 0x12345678;

определяет указатель const для целого числа и инициализирует его для указания в ячейке памяти 12345678. Вы можете изменить значение int по адресу 12345678, но вы не можете изменить адрес, на который указывает i3.

  • 4
    +1 Мне нравится этот ответ, потому что он определяет правильное и легкое в использовании правило. Хороший ответ.
21

const * char является недопустимым кодом C и не имеет смысла. Возможно, вы хотели спросить разницу между const char * и a char const *, или, возможно, разницу между a const char * и a char * const?

См. также:

12

const char* - указатель на постоянный символ char* const - постоянный указатель на символ const char* const - постоянный указатель на постоянный символ

7

1) const char * x Здесь X является главным образом символьным указателем, который указывает на постоянное значение

2) char * const x относится к указателю символа, который является постоянным, но местоположение, которое оно указывает, может быть изменено.

3) const char * const x является комбинацией с 1 и 2, означает, что это постоянный указатель на символ, который указывает на постоянное значение.

4) const * char x вызовет ошибку компилятора. он не может быть объявлен.

5) char const * x равно точке 1.

эмпирическое правило: если const имеет имя var, тогда указатель будет постоянным, но местоположение указателя может быть изменено, иначе указатель укажет на постоянное местоположение, а указатель может указывать на другое местоположение но содержимое указывающего местоположения не может быть изменено.

  • 0
    «char * const x относится к символьному указателю, который является постоянным, но местоположение, на которое он указывает, может быть изменено». Неправильно. Значение в местоположении может быть изменено не само местоположение.
4

Первый - синтаксическая ошибка. Возможно, вы имели в виду разницу между

const char * mychar

и

char * const mychar

В этом случае первый является указателем на данные, которые не могут быть изменены, а второй - указателем, который всегда будет указывать на тот же адрес.

3

Правило большого пальца: прочитайте определение справа налево!


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; будет недействительным.
2

Другое правило большого пальца - проверить, где const:

  • до * = > значение сохранено константа
  • после * = > указатель сам постоянный
1

Два правила

  • 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.
1

Модификатор const применяется к термину сразу слева. Единственное исключение - когда нет ничего, что осталось от него, тогда оно относится к тому, что сразу справа.

Это все эквивалентные способы сказать "постоянный указатель на константу char":

  • const char * const
  • const char const *
  • char const * const
  • char const const *
  • 0
    Это зависит от компилятора? gcc производит для "const char const *" и "const const char *" и "char const const *" один и тот же результат -> указатель может указывать на другое местоположение.
1

char * const и const char *?

  • Указание на постоянное значение

const char * p;//значение не может быть изменено

  1. Постоянный указатель на значение

char * const p;//адрес не может быть изменен

  1. Постоянный указатель на постоянное значение

const char * const p;//оба не могут быть изменены.

1
  • Указатель констант. Постоянный указатель может указывать только на одну переменную соответствующего типа данных в течение всей программы. Мы можем изменить значение переменной, указанной указателем. Инициализация должна выполняться во время самой декларации.

Синтаксис:

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;
}
  1. Указатель на значение const. В этом указатель может указывать любое количество переменных соответствующего типа, но мы не можем изменить значение объекта, указанного указателем в это конкретное время.

Синтаксис:

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;
    }
1

Вот подробное объяснение с кодом

/*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;
}*/
  • 0
    @reese Мур Спасибо.
1

Я предполагаю, что вы имеете в виду const char * и char * const.

Первый, const char *, является указателем на символ константы. Сам указатель изменен.

Второй, char * const - постоянный указатель на символ. Указатель не может быть изменен, характер, на который он указывает, может.

И тогда есть const char * const, где указатель и символ не могут измениться.

  • 0
    Первые два на самом деле одинаковы, а третий - ошибка компилятора :)
  • 0
    Упс, вы правы. Исправлена.
0

Множество ответов предоставляет конкретные методы, правило и т.д., чтобы понять этот конкретный экземпляр объявления переменных. Но существует общая методика понимания любого объявления:

Правило по часовой стрелке/спираль

А)

const char *a;

В соответствии с правилом по часовой стрелке/спирали a является указателем на постоянный символ. Это означает, что символ постоянный, но указатель может измениться. то есть a = "other string"; отлично, но a[2] = 'c'; не сможет скомпилировать

В)

char * const a;

В соответствии с правилом a является указателем const на символ. т.е. вы можете сделать a[2] = 'c';, но вы не можете сделать a = "other string";

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’
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню