Назначение const int * - PullRequest
       6

Назначение const int *

2 голосов
/ 27 февраля 2009
void main()
{
const int * a;
*a = 5;
}

gcc error: назначение места только для чтения.

Итак, как присвоить * a, не используя другую переменную? и что может быть использование объявления, как указано выше?

Ответы [ 7 ]

10 голосов
/ 27 февраля 2009
const int * a;

Прочитайте декларацию справа налево. [См. Примечание] Что вы получаете? a - это *, то есть указатель на int, то есть целое число const, то есть константа. Короче говоря, переменная a указывает на целое число, значение которого вы не можете изменить. По крайней мере, не через a. Является ли pointee действительно неизменным или нет, это другой вопрос. Но факт остается фактом, вы не можете использовать a для изменения *a;

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

Если вы действительно хотите написать в адрес пуанте, вам нужен неконстантный указатель, например:

int *a;
*a = 42; /* this is fine */

И очень хороший комментарий от bortzmeyer : (Я думал, что пропущу это, чтобы упростить его:)

Вы также можете поставить const после * (как вы сказали, объявления должны читаться справа налево).

Что он имеет в виду, это:

const int *a;

ничем не отличается от

int const *a;

(Помните, правило чтения справа налево?) Но сильно отличается от:

int * const p;

Прочтите его, и мы получим: p - это const (- муравей) * (указатель) на int (- эгер). Переведено: как только вы установите p для указания на целое число, вы не сможете переустановить его (т.е. записать в него, чтобы оно указывало на другое целое число - точку установления константы p), но вы можете написать в адрес получателя много (значение не постоянное).

Примечание: Для педантично наклонных здесь есть «Правило» от Даррон :

«объявления должны читаться справа налево» - это упрощение - если есть круглые скобки, их следует читать изнутри. Если в скобках не указан вызов функции. Настоящее правило - «относись к нему как к выражению; если я применю эти операторы, я в итоге получу этот простой тип».

В этом ответе действительно было бы гораздо меньше мяса, кроме bortzmeyer и Darron - спасибо!

PPS: (Я обещаю, что это будет последнее редактирование. Что ж, надеюсь!)

void main() не является стандартной подписью для main в C или C ++. Не используйте его, пока не узнаете себя или (что более важно), чтобы ваш код никогда не совершал путешествие в другую вселенную.

2 голосов
/ 27 февраля 2009

Позвольте мне задать ваш вопрос на простом английском.

  • Если я обещаю компилятору, что я не буду записывать значение, на которое указывает переменная a, как мне записать значение, на которое указывает переменная a?

Ответ: измените обещание, хотя бы локально.

int main()
{
    const int * a;
    *((int *) a) = 5;
}

Надеюсь, приведенная выше формулировка прояснит, что это обычно плохая идея.

2 голосов
/ 27 февраля 2009

Пример, иллюстрирующий превосходное объяснение Рубена Бартелинка:

#include <stdlib.h>

int main()
{
  int * const a = malloc(sizeof(int));
  if (a == NULL) 
    return 1;
  *a = 3;
  free(a);
  return 0;
}

Здесь a является константой (и, следовательно, должно быть инициализировано), но не * a (вероятно, того, что хотел OP).

1 голос
/ 27 февраля 2009

Вы имеете в виду int * const, а не const int *. В одном случае указатель является константным, а в другом материале, на который он указывает, является константой. Вы также можете сделать const int * const. Не вредно читать некоторые статьи о const_cast, они должны хорошо освещать эту тему.

0 голосов
/ 27 февраля 2009

Не отвечая на вопрос "как присвоить *, без использования другой переменной?" но только «что может быть использовано для объявления, как указано выше?».

Это обещание не изменять указанное значение. Как указано в комментарии, если вы наложите ограничения на то, как вы позволите себе использовать конструкцию, вы можете прийти к выводу, что она бесполезна. Но если вы позволите себе весь язык Си, тогда вы сможете найти применение. Подумайте о прототипе strcmp и подобных.

0 голосов
/ 27 февраля 2009

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

0 голосов
/ 27 февраля 2009

Не является ли точка с const, которую вы не можете присвоить ей? Хотя в случае с указателями const я не помню, можно ли изменить его значение, на которое он указывает, или адрес указателя. Или оба. Я думаю, что ни то, ни другое не может быть изменено.

Это также может быть общее предупреждение (или ошибка, в зависимости от настроек компилятора), которое вы пытаетесь записать в неинициализированную память.

Правильно было бы (я полагаю):

void main()
{
   const int* a = new int(5);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...