goksurahsan Ответов: 1

Указатели и операции с указателями


Всем привет;
Я нашел код выше. Но я не понимаю, где x=3 y=4. Пожалуйста, помогите мне.
Почему не сработали операции++, когда случай 0 повторялся дважды? И почему y=4, потому что я думаю, что это должно быть 5.

Что я уже пробовал:

#include<stdio.h>

int main(){
int x=2,y=3,*ptr,i=0;
int a[9]={1,2,3,4,5,6,7,8,9};

ptr=a;
//     printf("X= %d\n",x);
//     printf("*ptr= %d\n\n",*ptr);
while(i<5)
{
    //printf("i=%d\n",i);
    switch(i%3)
    {
    case 0:
        x=*(ptr)++;
//        printf("X= %d\n",x);
//        printf("*ptr= %d\n\n",*ptr);
    break;
    case 1:
       y=++*(ptr);
//       printf("Y= %d\n",y);
//       printf("*ptr= %d\n\n",*ptr);
    break;
    default:
        break;
    }
    i++;
    printf("x = %d\ty = %d\n",x,y);
}

return 0;
}

1 Ответов

Рейтинг:
4

OriginalGriff

Вы играете здесь с двумя вещами, ни одну из которых, я уверен, вы хорошо не понимаете.

Операции до и после инкремента могут быть трудны для понимания, потому что они являются операторами "побочного эффекта": они изменяют значение переменных без очевидного назначения.
В вашем случае,

x = *(ptr)++;
это эквивалент говорить об этом:
x = *ptr;
ptr = ptr + 1;
И
y = ++*(ptr);
это эквивалент этого:
*ptr = *ptr + 1;
y = *ptr;

Вторая версия изменяет значение в массиве a вместо того, чтобы изменять сам указатель.

Запустите код через отладчик и внимательно посмотрите, что происходит со значениями ptr и массив, и вы поймете, что я имею в виду.

Возможно, стоит быстро взглянуть сюда: Почему x = ++x + x++ дает мне неправильный ответ?[^] прежде чем вы начнете погружаться в сложные операторы до и после инкремента!


goksurahsan

Я понимаю до и после инкремента раньше. Но на самом деле я спрашиваю об этом действии, почему, когда i=3 post-increment не работал для ptr. Я использовал отладчик, но debeugger показал мне, что постинкремент прошел

OriginalGriff

Это сработало отлично. Он сделал именно то, что вы ему сказали.

goksurahsan

Например я думаю что эти коды такие же как и предыдущие коды:

случай 0:
x=*(ptr);
*ptr=*ptr+1;
//x=*ptr++;
// printf("X= %d\n",x);
// printf("*ptr= %d\n\n",*ptr);
перерыв;
корпус 1:
*(ptr)=*(ptr)+1;
y=*(ptr);
//y=++(*ptr);

Richard MacCutchan

Нет, смотрите мой комментарий ниже.

Richard MacCutchan

Не совсем. Второй случай эквивалентен:

y = *ptr;
y = y + 1;

ptr в этом случае не увеличивается.

Мне потребовалось полчаса, чтобы понять это.

goksurahsan

Но ++ рядом с ptr. Я должен это изменить ptr. Это правда?

Richard MacCutchan

Нет, * ближе всего к ptr, поэтому он сначала выполняет операцию косвенного обращения, то есть принимает значение (*ptr) и увеличивает его, но не увеличивает указатель.

OriginalGriff

- Вы уверены?
Это предварительное приращение, и если я проверю его в VS:
тап_п()
{
int arr[5] = { 10, 21, 32, 43, 54 };
int* p = arr;
int x = ++ * p;
возвращает 0;
}Я получаю arr[0] == 11, x == 11, p == arr[0], как и ожидал.

Richard MacCutchan

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

OriginalGriff

Они также время от времени забивают мне голову ... :смеяться:

Richard MacCutchan

И я все время писал такие вещи еще в мои чистые дни си. Заметьте, я сомневаюсь, что когда-либо правильно его понимал.

OriginalGriff

То же.
И самое худшее еще впереди ... если ОП не проследил за ссылкой на статью, которую я ему дал, он действительно запутается со своей следующей попыткой - они также являются зависимыми от реализации операторами побочных эффектов ... :EvilLaughSmiley:

goksurahsan

И хотя эти коды работают так, как я думал, почему процесс инкремента не работает в предыдущем коде, когда i = 3 в разделе * (ptr) ++. К сожалению, это та часть, которую я не понимаю.

OriginalGriff

Оно делает. Прочтите, что мы сказали выше. ++*P изменило значение, что P указывает, а не значение P.
Но поскольку ваши числа в массиве также увеличиваются на единицу, трудно сказать, если вы не посмотрите внимательно.
Отладчик покажет вам это, если вы посмотрите на ptr и содержимое массива.

Richard MacCutchan

Потому что после первого случая 0 a = { 1,2,3,4 ...} и ptr указывает на 2
Затем мы переходим к случаю 1: ptr указывает на 2, который изменяется на 3. y получает 3.
таким образом, a теперь равно {1,3,3,4 ...};
В следующий раз, когда мы доберемся до случая 0, x получит 3 (первые 3), а ptr будет изменен, чтобы указать на вторые 3.
В следующем случае 1 второй 3 изменяется на 4, так что a = { 1,3,4,4, ...} и y получает первый 4.

Измените числа в массиве на несмежные (например, { 3,7,15,22 }), и он станет более ясным.

Примечание: приношу извинения за мое предыдущее "решение", оно было неверным.

goksurahsan

Правда, большое вам спасибо. Я не мог понять, потому что был новичком в Си. Теперь я понимаю. В то время как адрес, указанный указателем, изменяется в разделе x = * ptr++, значение y изменяется в соответствии с адресом, указанным ptr в разделе y = ++ * ptr.

OriginalGriff

Close - значение того, на что указывает ptr, изменяется, и это влияет на то, что записывается в y.

goksurahsan

Да, теперь я понимаю. Спасибо Вам еще и еще раз. Сегодня я узнал кое-что новое :)

OriginalGriff

Всегда пожалуйста!