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

В чем разница между следующими объявлениями?

char * const a;
const char * a;

Чтобы понять разницу, я написал эту небольшую программу:

#include <stdio.h>
#include <stdlib.h>


int main (int argc, char **argv)
{
    char a = 'x';
    char b = 'y';

    char * const pc1 = &a;
    const char * pc2 = &a;

    printf ("Before\n");
    printf ("pc1=%p\n", pc1);
    printf ("*pc1=%c\n", *pc1);
    printf ("pc2=%p\n", pc2);
    printf ("*pc2=%c\n", *pc2);

    *pc1 = b;
/*     pc1 = &b; */

/*     *pc2 = b; */
    pc2 = &b;

    printf ("\n\n");

    printf ("After\n");
    printf ("pc1=%p\n", pc1);
    printf ("*pc1=%c\n", *pc1);
    printf ("pc2=%p\n", pc2);
    printf ("*pc2=%c\n", *pc2);

    return EXIT_SUCCESS;
}

Я скомпилировал программу (с gcc 3.4) и запустил ее. Результат очень хорошо показывает разницу:

Before
pc1=ffbfd7e7
*pc1=x
pc2=ffbfd7e7
*pc2=x


After
pc1=ffbfd7e7
*pc1=y
pc2=ffbfd7e6
*pc2=x

Однако мне пришлось написать небольшую программу, чтобы получить ответ. Если я уйду от машины (например, в интервью), я не смогу ответить на вопрос.

Может кто-нибудь объяснить, комментируя приведенный выше пример, как работает ключевое слово const?

Ответ 1

char * const a;

означает, что указатель является постоянным и неизменным, но зато указанными данными нет.
Вы можете использовать const_cast (в С++) или c-style cast, чтобы отбросить константу в этом случае, поскольку сами данные не являются постоянными.

const char * a;

означает, что указанные данные не могут быть записаны с использованием указателя a. Используя приведение const_cast (С++) или c-style для отбрасывания константы в этом случае вызывает Undefined Поведение.

Ответ 2

char * const a;

*a доступен для записи, но a не является; другими словами, вы можете изменить значение, на которое указывает a, но вы не можете изменить a. a - постоянный указатель на char.

const char * a; 

a доступен для записи, но *a не является; другими словами, вы можете изменить a (указывая его на новое место), но вы не можете изменить значение, на которое указывает a.

Обратите внимание, что это идентично

char const * a;

В этом случае a является указателем на const char.

Ответ 3

Чтобы разобрать сложные типы, вы начинаете с переменной, идите влево и спирали наружу. Если нет каких-либо массивов или функций, о которых можно беспокоиться (потому что они сидят справа от имени переменной), это становится примером чтения справа налево.

Итак, с char *const a; у вас есть a, который является указателем const (*) на char. Другими словами, вы можете изменить char, на который указывает a, но вы не можете сделать a на что-то другое.

Наоборот, с const char* b; у вас есть b, который является указателем (*) на char, который равен const. Вы можете сделать b точку в любом char, который вам нравится, но вы не можете изменить значение этого char с помощью *b = ...;.

Вы также можете, конечно, иметь оба вкуса константы за один раз: const char *const c;.

Ответ 4

Теперь вы знаете разницу между char * const a и const char * a. Много раз мы путаем, если его постоянный указатель или указатель на постоянную переменную.

Как это прочитать? Выполните следующий простой шаг, чтобы определить между двумя верхними.

Давайте посмотрим, как читать ниже декларации

char * const a;

читать справа налево

Теперь начните с a,

1. рядом с a существует const.

char * (const a);

--- > Итак, a - это constant (????).

2. Теперь идите, вы получите *

char (* (const a));

--- > Итак, a - это constant pointer to (????).

3. Идите вперед и там char

(char (* (const a)));

--- > a является переменной constant pointer to character

a is constant pointer to character variable. 

Легко ли читать?

Сходство для второго объявления

const char * a;

Теперь снова начинаем с a,

1. Рядом с a есть *

--- > Итак, a - это pointer to (????)

2. Теперь существует char

--- > поэтому a есть pointer character,

Ну, это не имеет никакого смысла!!! Итак, перетасуйте pointer и character

--- > поэтому a есть character pointer до (?????)

3. Теперь у вас есть constant

--- > поэтому a есть character pointer to constant variable

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

a is pointer to constant character variable

Ответ 5

Самый простой способ понять разницу - подумать о разных возможностях. Есть два объекта для рассмотрения: указатель и объект, на которые указывает (в этом случае "a" - это имя указателя, указанный объект не указан, типа char). Возможны следующие варианты:

  • ничего не const
  • указатель const
  • объект, на который указывает объект const
  • и указатель, и указатель на объект являются константами.

Эти различные возможности могут быть выражены в C следующим образом:

  • char * a;
  • char * const a;
  • const char * a;
  • const char * const a;

Я надеюсь, что это иллюстрирует возможные различия

Ответ 6

Первый - постоянный указатель на char, а второй - указатель на константу char. Вы не касались всех случаев в своем коде:

char * const pc1 = &a; /* You can't make pc1 point to anything else */
const char * pc2 = &a; /* You can't dereference pc2 to write. */

*pc1 = 'c' /* Legal. */
*pc2 = 'c' /* Illegal. */

pc1 = &b; /* Illegal, pc1 is a constant pointer. */
pc2 = &b; /* Legal, pc2 itself is not constant. */

Ответ 7

Сначала я объясню это в устной форме, а затем с примером:

Объект-указатель может быть объявлен как указатель const или указатель на объект const (или оба):

A указатель const нельзя переназначить, чтобы указать на другой объект из того, который он первоначально назначил, но его можно использовать для изменения объекта, на который он указывает (называемый "pointee" ).
Таким образом, ссылочные переменные являются альтернативным синтаксисом для constpointers.

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

A const указатель на объект const также может быть объявлен и не может использоваться для изменения указателя и не переназначается для указания на другой объект.

Пример:

void Foo( int * ptr,
         int const * ptrToConst,
         int * const constPtr,
         int const * const constPtrToConst ) 
{ 
    *ptr = 0; // OK: modifies the "pointee" data 
    ptr = 0; // OK: modifies the pointer 

    *ptrToConst = 0; // Error! Cannot modify the "pointee" data
     ptrToConst = 0; // OK: modifies the pointer 

    *constPtr = 0; // OK: modifies the "pointee" data 
    constPtr = 0; // Error! Cannot modify the pointer 

    *constPtrToConst = 0; // Error! Cannot modify the "pointee" data 
    constPtrToConst = 0; // Error! Cannot modify the pointer 
}

Счастлив помочь! Удачи!

Ответ 8

Выше - отличные ответы. Вот простой способ запомнить это:

a - указатель

* a - значение

Теперь, если вы скажете "const a", указатель будет const. (т.е. char * const a;)

Если вы скажете "const * a", то значение будет const. (т.е. const char * a;)

Ответ 9

Вы можете использовать утилиту cdecl или ее онлайн-версии, например http://www.lemoda.net/c/cdecl/

Например:

void (* x)(int (*[])()); это declare x as pointer to function (array of pointer to function returning int) returning void

Ответ 10

Попытка ответить простым способом:

char * const a;  => a is (const) constant (*) pointer of type char {L <- R}. =>( Constant Pointer )
const char * a;  => a is (*) pointer to char constant             {L <- R}. =>( Pointer to Constant)

Постоянный указатель:

указатель постоянный!!. то есть адрес, который он удерживает, не может быть изменен. Он будет сохранен в памяти только для чтения.

Попробуйте изменить адрес указателя, чтобы понять больше:

char * const a = &b; 
char c;
a = &c; // illegal , you can't change the address. `a` is const at L-value, so can't change. `a` is read-only variable.

Это означает, что когда постоянный указатель указывает какую-то вещь навсегда.

указатель a указывает только b.

Однако вы можете изменить значение b например:

char b='a';
char * const a =&b;

printf("\n print a  : [%c]\n",*a);
*a = 'c';
printf("\n now print a  : [%c]\n",*a);

Указатель на константу:

Значение, указанное указателем, не может быть изменено.

const char *a;
char b = 'b';
const char * a =&b;
char c;
a=&c; //legal

*a = 'c'; // illegal , *a is pointer to constant can't change!.

Ответ 11

const char * a;

Указывает указатель на постоянный символ. Например,

char b='s';
const char *a = &b;

Здесь a указывает на константу char ('s', в этом случае). Вы не можете использовать a для изменения этого значения. Но это объявление не означает, что значение, на которое оно указывает, равно действительно константа, это просто означает, что значение является константой, поскольку речь идет о a. Вы можете напрямую изменить значение b, изменив значение b, но вы не можете косвенно изменить значение с помощью указателя a.

*a='t'; //INVALID b='t' ; //VALID

char * const a=&b

Указывает постоянный указатель на char. Ограничения a указывают только на b, но это позволяет вам изменить значение b.

Надеюсь, это поможет!!!:)