Pointer Arithmeti c - Проблемы с массивом и указателем на массив - PullRequest
0 голосов
/ 07 мая 2020

Недавно я переключился на C и пытался вычислить указатели.

#include <stdio.h>

int main()
{
    int arr[5] = {1,2,3,4,5};
    int *a = &arr;

    printf("Array : %p\n", arr);
    for(int i=0; i<5; i++)
    {
        printf("Value and Address of Element - %d : %d\t%p,\n", i+1, arr[i], &arr[i]);
    }
    printf("Pointer to the Array : %p\n", a);
    printf("Value pointed by the pointer : %d\n", *a);
    a = (&a+1);
    printf("Pointer after incrementing : %p\n", a);
    return 0;
}

Однако следующая строка, похоже, не работает.

a = (&a+1);

После печати увеличенного значения указателя a он все еще указывает на массив (arr). Вот результат работы программы:

Array : 0x7ffe74e5d390
Value and Address of Element - 1 : 1    0x7ffe74e5d390,
Value and Address of Element - 2 : 2    0x7ffe74e5d394,
Value and Address of Element - 3 : 3    0x7ffe74e5d398,
Value and Address of Element - 4 : 4    0x7ffe74e5d39c,
Value and Address of Element - 5 : 5    0x7ffe74e5d3a0,
Pointer to the Array : 0x7ffe74e5d390
Value pointed by the pointer : 1
Pointer after incrementing : 0x7ffe74e5d390

Как вы можете видеть, указатель «a» по-прежнему указывает на первый элемент. Однако теоретически не должно 'a' указывать на все, что находится после последнего элемента (учитывая, что & a + 1 увеличивает указатель на размер всего массива - источник: разница между a + 1 и & a + 1 )

Кто-нибудь может объяснить почему?

Ответы [ 2 ]

1 голос
/ 07 мая 2020

a = (&a+1); устанавливает a для указания на одну «вещь» помимо адреса a.

Раньше ваш код устанавливает a на &arr, используя int *a = &arr;. (Это нарушает стандартные ограничения C, потому что тип &arr является указателем на массив, а не указателем на int. Правильным определением будет int *a = arr;.) Я подозреваю, что ваше намерение в a = (&a+1); было чтобы установить a, чтобы он указывал на точку за пределами того места, где он сейчас указывает. Однако правильный код для этого будет a = a+1;. Это принимает значение из a, прибавляет к нему единицу и присваивает результат a. Напротив, a = (&a+1); использует адрес a вместо своего значения.

Это приводит к тому, что a указывает на один за пределами того места, где a находится в памяти. В вашем эксперименте кажется, что здесь оказался массив arr, и ваша реализация C вела себя соответствующим образом.

(Это объясняет наблюдаемые вами результаты, но на это не следует полагаться. Стандарт C не определяет, что происходит при неправильном использовании указателей таким образом, и различные вещи, включая оптимизацию компилятора, могут привести к тому, что программы будут вести себя так, как если бы &a+1 не указывал на arr, даже если arr находится в факт находится по адресу &a+1 в памяти.)

0 голосов
/ 07 мая 2020

В этом конкретном случае переменная и массив могут быть помещены в стек, как показано ниже, что не гарантируется стандартом. Каждая ячейка - int. Вы помните, что адрес стека уменьшается для каждой размещенной локальной переменной.

+-+-+-+-+-+-+
|a|1|2|3|4|5|
+-+-+-+-+-+-+

&a+1, это не адрес массива, вы берете адрес a, перемещаетесь на одну ячейку и получаете адрес массива в результате.

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