Массив как константный указатель - PullRequest
6 голосов
/ 01 октября 2010

Рассмотрим следующий код:

void Increment(int *arr) {
    arr++;
}

int main() {
    int arr[] = {1,2,3,4,5};
    // arr++  // illegal because its a const pointer
    Increment(arr);   // legal
}

Мой вопрос: если arr является указателем const, почему я могу отправить его функции, которая не получает указатель const?

Код компилируется без предупреждения об отмене квалификаторов const.

Ответы [ 8 ]

10 голосов
/ 01 октября 2010

Мой вопрос: если arr является константным указателем, почему я могу отправить его функции, которая не получает константный указатель?

arr (внутри main()) это не константный указатель, это массив.Тип массива превращается в тип указателя при передаче в функцию.

arr (параметр) внутри Increment содержит копию адреса аргумента arr (передается по значению из main()).

// arr ++// ileagal, потому что это константный указатель

Это недопустимо, потому что arr является неизменяемым lvalue.

7 голосов
/ 01 октября 2010

Не обманывайтесь указателем. То же самое верно для простых целых:

const int a = 42;
int b = a; // How can I assign a const int to a non-const int?
int c = 4; // Come to think of it, the literal 4 is a constant too
void foo (int x) { std::cout << x; }
foo(a); // How come I can call foo with a const int?

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

3 голосов
/ 01 октября 2010

Причина, по которой вы не можете увеличить int arr[] в main, заключается в том, что это не модифицируемое lvalue.Стандарт гласит:

Изменяемое значение lvalue - это значение lvalue, которое не имеет типа массива, не имеет неполного типа, не имеет типа с константой, и если это структура или объединение, не имеет ни одного члена (включая, рекурсивно, ни одного члена или элемента из всех содержащихся агрегатов или объединений) с квалифицированным const типом.

Оператору приращения ++ требуется изменяемое значение lvalueэто изменяет).Однако указатель в функции Increment является изменяемым значением lvalue (это не тип массива, это указатель), поэтому он допустим там.

1 голос
/ 01 октября 2010

Тип arr внутри функции отличается от типа arr в main. Вы просто дали им одно и то же имя.

main - это массив, и я удивлен, что его объявление компилируется. Обычно вы делаете:

int arr[] = {1,2,3,4,5};

Но 'arr' в функции - это простой указатель, поэтому его можно увеличивать.

Если добавить, в основном,

int *arr2 = arr;

Тогда вам лучше повезет, увеличивая arr2. Или вы можете добавить индекс, который можно увеличивать и использовать для индексации в массиве arr.

1 голос
/ 01 октября 2010

Вы не увеличиваете массив в main (), вы увеличиваете локальную переменную (параметр) в Increment ()

0 голосов
/ 01 октября 2010

arr - это указатель const типа int, который содержит адрес первого элемента, здесь адрес значения 1. const определяет, что адрес, содержащийся в arr, изменить нельзя.Это утверждение инкремент (обр);передает адрес, содержащийся в arr, который имеет тип int *, поэтому компилятор не жалуется.

0 голосов
/ 01 октября 2010

Мой вопрос: если arr является константным указателем

Это не указатель const.

Вот как вы объявляете константный указатель.

const char constArray[] = { 'H', 'e', 'l', 'l', 'o', '\0' };

Стандарт C (C99 6.3.2.1/3) гласит: «За исключением случаев, когда это операнд оператора sizeof или унарный оператор &, или строковый литерал, используемый для инициализации массива, выражение, котороеимеет тип '' массив типа '', преобразуется в выражение с типом '' указатель на тип '', которое указывает на начальный элемент объекта массива и не является lvalue.

int b[100];    // b is an array of 100 ints.
int* p;        // p is a pointer to an int.
p = b;         // Assigns the address of first element of b to p.
p = &b[0];     // Exactly the same assignment as above.

p = b;   // Legal -- p is not a constant.
b = p;   // ILLEGAL because b is a constant, altho the correct type.

Источник: http://www.fredosaurus.com/notes-cpp/arrayptr/26arraysaspointers.html

0 голосов
/ 01 октября 2010

Это потому, что функция Increment только меняет свою локальную версию arr, а arr в main () области видимости фактически не изменяется. Поэтому const для переменных не учитывается в терминах параметров функции.

void func(void* param) {}

int main() {
  void *a;
  void *const b;
  void const *c;
  void const *const d;
  func(a);  // legal
  func(b);  // legal, constantness of variable doesn't matter, because the function can't change it anyway
  func(c);  // illegal
  func(d);  // illegal
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...