Различные выходные данные '& имя_массива + n' внутри и вне основной функции

avatar
19aksh
9 августа 2021 в 02:38
81
2
2

Выражение &arrayname + n должно давать base address + (number of elements * size of type of elements) * n, и внутри функции main() оно работает должным образом.

Но если я использую то же самое в другой функции, оно интерпретируется по-другому и выдает другой результат.

Код (32-битный компилятор):

#include <stdio.h>
void arrf(int A[],int n)
{
printf("\n\nInside arrf()");
printf("\n&A ---> %p",A);
for(int i=0;i<n;i++)
    printf("\n&A + %d  ---> %p",i,(&A+i));
}

int main()
{
int A[]={1,2,3,4,5};
int n=5;
printf("Inside main()");
printf("\n&A --->%p",A);
for(int i=0;i<n;i++)
    printf("\n&A + %d  ---> %p",i,(&A+i));
arrf(A,n);
return 0;
}

Вывод образца:

Inside main()
&A --->0x7ffed323eac0
&A + 0  ---> 0x7ffed323eac0
&A + 1  ---> 0x7ffed323ead4
&A + 2  ---> 0x7ffed323eae8
&A + 3  ---> 0x7ffed323eafc
&A + 4  ---> 0x7ffed323eb10

Inside arrf()
&A ---> 0x7ffed323eac0
&A + 0  ---> 0x7ffed323ea88
&A + 1  ---> 0x7ffed323ea90
&A + 2  ---> 0x7ffed323ea98
&A + 3  ---> 0x7ffed323eaa0
&A + 4  ---> 0x7ffed323eaa8

Внутри main(), &A+1 дает 0x7ffed323eac0 + Hex(5*4*1) = 0x7ffed323eac0 + 0x14 = 0x7ffed323ead4, как и ожидалось, как и выходные данные для всех &A+i

Но в функции arrf() выходные данные не такие, как ожидалось, даже &A+0 выдает выходные данные, отличные от базового адреса. Что еще более странно, адреса уменьшаются, а не увеличиваются. Почему?

Источник
WhozCraig
9 августа 2021 в 02:41
0

(&A+i) — автоматический запах кода. Это следует рассматривать как подтверждение того, что вам нужно лучше понять, как работает арифметика указателей и что на самом деле представляет собой тип выражения &A. В данном случае int (*)[5] в main. Но так как A является простым `int*` в списке параметров функции, &A там int**. Таким образом разница.

Roflcopter4
9 августа 2021 в 02:46
1

Могу я спросить, почему, во имя святого имени Денниса Ричи, вы вообще берете адрес этой переменной? Использование адреса массива стека почти никогда не имеет смысла.

Tom Karzes
9 августа 2021 в 02:46
0

В main A имеет тип int [5], но в arrf A имеет тип int *. В то время как добавление целого числа к A будет работать одинаково в обеих функциях, добавление целого числа к &A не будет, так как &A имеет тип int (*)[5] в main и int ** в <84777919830>. Эти два типа совершенно разные и несовместимы.

n. 1.8e9-where's-my-share m.
9 августа 2021 в 04:32
1

Обратите внимание, что если x является переменной (любого типа), то (&x + n) является неопределенным поведением всякий раз, когда n > 1.

U. Windl
9 августа 2021 в 08:31
0

@AK Итак, если вы поняли, напишите ответ и примите это ради других.

19aksh
9 августа 2021 в 13:45
0

@U.Windl Я уже принял ответ dbush

Ответы (2)

avatar
dbush
9 августа 2021 в 02:44
3

Когда массив передается функции, он преобразуется в указатель на его первый элемент. Итак, A в main — это массив, а A в arrf — указатель.

Это также означает, что в arrf этот &A имеет тип int **, поэтому арифметические операции с указателями выполняются в единицах int *, размер которых в вашей системе, по-видимому, равен 8.

Кроме того, A в arrf является отдельной переменной от A в main, поэтому ее адрес будет другим (скорее всего, в стеке программы).

19aksh
9 августа 2021 в 03:25
0

Спасибо. Итак, &A + 0 отличается от &A в функции arrf() и тем, что для каждого ```i`` он увеличивается на 8 байтов, поскольку размер указателя равен 8 в 32-битном компиляторе?

avatar
InQusitive
9 августа 2021 в 03:41
1

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

Я изменил пример, чтобы он работал.

#include <stdio.h>
void arrf(int (*A)[5],int n)//Here
{
  printf("\n\nInside arrf()");
  printf("\n&A ---> %p",A);
  for(int i=0;i<n;i++)
        printf("\n&A + %d  ---> %p",i,(A+i));
}

int main()
{
  int A[]={1,2,3,4,5};
  int n=5;
  printf("Inside main()");
  printf("\n&A --->%p",A);
  for(int i=0;i<n;i++)
        printf("\n&A + %d  ---> %p",i,(&A+i));
        arrf(&A,n);//Here
        return 0;
}

Также читайте о: c-указатель-на-массив-массив-указателей-устранение неоднозначности

klutt
9 августа 2021 в 04:06
1

"Когда вы передаете адрес массива в функцию, он превращается в указатель" — адрес не превращается в указатель. Это уже указатель. Если вы передадите массив (а не адрес массива), он превратится в указатель.

klutt
9 августа 2021 в 04:20
1

"Когда вы передаете адрес массива в функцию, у него нет информации" - Не уверен, что вы пытаетесь сказать. Это также верно, если вы передаете массив напрямую, но ваш пост создает впечатление, что это не так.