Понимание C-указателей, инкремент и разыменование - PullRequest
0 голосов
/ 03 января 2019

Мне дана программа, и я должен предсказать ее вывод.

Я пытался шаг за шагом понять программу и записать значение переменных в каждой точке программы, но я не уверен, что делают эти операции:

increment(&i); increment(&a[i]);

#include<stdio.h> 

void increment(int *ptr){
    ++ *ptr;
} 

int main(){ 
    int a[]={5,10},i=0; 
    increment(a); 
    increment(&i); 
    increment(&a[i]); 
    increment(a+i);
    printf("\nResult:i=%d\n",i); 
    printf("a[0]=%d\n a[1]= %d\n", a[0], a[1]);
    return 0 ;
}

Решение:

Result: i = 1 
a[0] = 6
a[1] = 12

Не могли бы вы помочь мне понять, как я могу получить решение?Спасибо!

Ответы [ 4 ]

0 голосов
/ 03 января 2019

Давайте начнем с некоторой справочной информации.

Сначала выражение ++i оценивается в текущее значение i плюс 1 - как побочный эффект , значение, сохраненное в i, увеличивается на единицу. Как автономное выражение, оно примерно эквивалентно i = i + 1.

Во-вторых, за исключением случаев, когда это операнд операторов sizeof или унарных &, выражение типа "массив N-элементов T" (T [N]) будет преобразуется («распад») в выражение типа «указатель на T» (T *), а значением выражения будет адрес первого элемента массива.

Наконец, выражение a[i] является , определенным как *(a + i) - с учетом начального адреса a, смещение i элементов (не байтов!) От этого адреса и разыменовывать результат. Это означает, что выражение a + i эквивалентно выражению &a[i].

Посмотрим, как это относится к вашему коду:

В функции increment строка

++ *ptr;

добавляет 1 к вещи, на которую указывает ptr.

Когда вы вызываете increment(a), выражение a имеет тип "массив из 2 элементов int". Поскольку a не является операндом операторов sizeof или унарных &, это выражение «затухает», чтобы ввести «указатель на int» (int *), а значение выражения является адресом первый элемент a. Точно так же, как если бы вы написали increment(&a[0]). Следовательно, в функции increment выполняются следующие условия:

 ptr == &a[0]
*ptr ==  a[0]

Таким образом, выражение ++ *ptr эквивалентно выражению ++ a[0]. После этого звонка a[0] теперь 6.

Когда вы звоните increment(&i), ptr теперь указывает на i:

 ptr == &i
*ptr ==  i

поэтому ++ *ptr эквивалентно выражению ++ i, поэтому вы добавляете 1 к i.

Когда вы звоните increment(a[i]), i равен 1, так что это эквивалентно вызову increment(a[1]). После этого вызова a[1] равно 11.

И, наконец, increment(a+i) эквивалентно increment(&a[i]), что эквивалентно increment(&a[1]), а после этого вызова a[1] равно 12.

0 голосов
/ 03 января 2019

Функция increment(int *ptr) ожидает указатель на int, то есть на адрес.

Поскольку переменная i имеет тип int, вы должны передать ее адрес с помощью address-of оператор & как в: increment(&i)

a[i] равен *(a+i) - т.е. вы обращаетесь к адресу элемента массива в a+i и разыменовываете его вЧтобы получить значение этого элемента массива в позиции i.
По той же причине, что и в первом случае, increment ожидает указатель и, следовательно, вы должны передать адрес, как в: increment(&a[i]);

0 голосов
/ 03 января 2019

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

#include<stdio.h> 
// This function takes a pointer to int and increments the pointed value
void increment(int *ptr){++ *ptr;}      

int main(){ 
    int a[]={5,10},i=0; // It doesn't look so but here, a is a pointer to int
    increment(a);       // increments the first value pointed by a (a[0]) so now a is [6,10]
    increment(&i);      // increments i, now i = 1
    increment(&a[i]);   // increments a[1], now a = [6,11]
    increment(a+i);     // since i = 1, increments the value right after the one pointed by a so again, a[1], now a = [6,12]
    printf("\nResult:i=%d\n",i);        
    printf("a[0]=%d\n" "a[1]= %d\n");
    return 0 ;
}
0 голосов
/ 03 января 2019

но я не уверен, что делают эти операции:

increment(&i); передает адрес переменной i в вашу функцию приращения. Эта функция разыменовывает указатель и увеличивает указатель на значение, которое по существу эквивалентно i++.

increment(&a[i]) делает то же самое, но теперь он передает адрес i -ого элемента a. Поскольку i был увеличен до 1 ранее, это эквивалентно a[1]++.

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