2015-01-16 2 views
0

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

#include<iostream> 
using namespace std; 
void change(int *b,int n) 
{ 
    int i; 
    for(i=0;i<n;++i) 
     *(b+i)=*(b+i)+5; 
} 
int main() 
{ 
    int a[]={2,4,6,8,10}; 
    int i; 
    change(a,5); 
    for(i=0;i<=4;++i) 
     cout<<a[i]<<"\n"; 

} 

Здесь в функции change утверждение в цикле for дает мне проблему. В этом операторе присваивания в левой части *(b+i) хранится значение *(b+1)+5, но как получается, что значение сохраняет другое значение как *(b+i), дает значение каждый раз, скажем для первой итерации i is 0, которая выражает выражение *(b+0)=*(b+0)+5. Таким образом, LHS здесь 7, а RHS - 2, что дает 2 = 7. Не следует ли давать ошибку, например, требуемую lvalue или что-то в этом роде?

+0

Сторона: верхняя ссылка в соответствующем списке справа от этого вопроса может оказаться образовательной. И ваш код вызывает * неопределенное поведение *. Последняя итерация через ваш цикл записывает и считывает из памяти один элемент за пределами вашего объявленного размера. – WhozCraig

ответ

3

В C++ *(b+x) является синтаксическим лимон (а) для:

b[x] 

так что вы должны прочитать его в виду. Другими словами, заявление вы спрашиваете вопрос о том, будет лучше записать в виде:

b[i] = b[i] + 5; 

(а) Противоположностью синтаксического сахара, очевидно. Так названо, потому что, в то время как синтаксический сахар является более легким для чтения эквивалентом, синтаксический лимон труднее читать.

Если ваш ум не является, как у меня, так что деформированные от лет воздействия C, что она легко принимает такого рода вещи в ходу :-)

0

Как отметил paxdiablo, это в основном просто намеренно плохо написанный код (возможно, чтобы проверить или увеличить ваше понимание синтаксиса C++).

Во-первых, какие изменения (интермедиат * б, Int N) делает:

Как уже отмечалось, *(a+i) дает значение на "указатель а, увеличился на я шагов". Так что изменение() делает это следующим образом: Он перебирает все значения I от 0 до чуть ниже п (для цикла) и выполняет

*(b+i)=*(b+i)+5;

означает Это последнее утверждение: принимать значение в «указателе b, увеличено на i шага ", а затем ASSIGN к нему (ничего общего с проверкой равенства!) значение, которое может быть найдено на« указателе b, увеличенном на i шагах », увеличено на 5.

Что он делает Короче говоря, нужно перебрать int-array b [] длины n (адресованного в C-стиле по его базовому адресу указателя b) и увеличить все содержащиеся целые числа на 5.

Остальная часть основной программы выводит измененные значения на консоль.

Если практические вопросы в источнике, который вы используете для изучения C++, все это похоже на это, я бы предположил, что, возможно, переключитесь на другой курс. Хотя понимание синтаксиса важно, существуют и другие концепции, которые по меньшей мере столь же важны в современном объектно-ориентированном программировании (например, правильное использование библиотек, наследование, ремонтопригодность кода, ...).

1

Результатом работы оператора * всегда является lvalue, поэтому назначение является законным.

Результат * [ссылка на] объект, на который указывает его операнд, а не только значение объекта.

Чтение *(b + 0) = *(b + 0) + 5 как «объект на месте b + 0 получает значение объекта в b + 0 плюс 5.

(Как и в стороне, причина того, что второй b + 0 обрабатывает это значение, так как он используется в контекст выражения (как операнд арифметического оператора +), где требуется его значение, а не потому, что это результат применения оператора разыменования, который, как упоминалось выше, приводит к lvalue. Этот артефакт «рассматривать как значение» известное как «преобразование значения lvalue-to-rval» и происходит неявно, где необходимо.)

+0

'Результат оператора * всегда равен lvalue, поэтому назначение является законным.' Это всегда верно даже в приведенном ниже примере int a = 10, * b; б = & а; соиЬ << * б; // Но здесь nt здесь он просто дал значение r –

+0

. Итак, вы говорите, что в приведенном выше коде было неявное значение lvalue для rvalue rt? –

+1

Да, существует неявное lvalue для преобразования rvalue на '* b' в' cout << * b', но также будет один из 'a' (другое значение lvalue) в' cout << a'. –

Смежные вопросы