Как мне обращаться с указателями массива? - PullRequest
1 голос
/ 07 сентября 2011

Эта программа правильно печатает все выходы массивов. Но как именно эта программа работает? Зачем нам нужен адрес s[i] здесь?

#include <stdio.h>

int main(){
        int s[4][2] = {{1234,1},{1233,2},{1232,3},{1331,4}};
        int (*p)[2];
        int i,j,*pint;

        for(i=0;i<4;++i){
                p = &s[i];
                pint = (int*)p;
                printf("\n");
                for(j=0;j<=1;++j)
                        printf("%d ",*(pint+j));
        }
        return 0;
}

Ответы [ 3 ]

2 голосов
/ 07 сентября 2011

int (*p)[2] - указатель на тип int [2], который сам по сути является типом int *, но с некоторой дополнительной проверкой типа на границах массива.

Таким образом, в p = &s[i]; вы устанавливаете p как адрес указателя на область памяти, где находится массив s[i].

Гораздо проще просто сделать p также массивом (т. Е. «По существу» указателем на область памяти с дополнительным оборудованием), а затем использовать его непосредственно для указания на область памяти массива (p = s[i] ). Однако в этом случае это именно то, что делает pint (как истинный указатель), поэтому мы можем полностью удалить p.

Итак:

#include <stdio.h>

int main(){
        int s[4][1] = {{1234,1},{1233,2},{1232,3},{1331,4}};
        int i,j,*pint;

        for(i=0;i<4;++i){
                pint = (int*)s[i];
                printf("\n");
                for(j=0;j<=1;++j)
                        printf("%d ",*(pint+j));
        }
        return 0;
}

См. Массивы и указатели или google для "Массивы и указатели C", а также Адрес указателя в многомерном массиве C .

Заметьте, я предполагаю, что вы просто делаете это, чтобы поиграть и понять, как взаимодействуют указатели и массивы, поэтому я не комментирую, идеально ли использовать арифметику указателей или понятие массива и т. Д. В каждом случае.


Заметьте также, что я говорю, что массив - это «по существу указатель [...]», однако это не совсем верно, во многих случаях он просто действует как указатель, и по большей части это разумный способ думать о том, как все работает. В действительности к массивам относятся особым образом. См. Является ли имя массива эквивалентным указателю? и Массивы .

1 голос
/ 07 сентября 2011

Тьфу. Я не уверен, что этот код должен иллюстрировать, кроме как сделать простой для понимания код сложным для понимания.

s - это 4-элементный массив из 2-элементных массивов int. То есть для i в 0..3 тип s[i] равен int [2] (который в большинстве контекстов уменьшается до int *), а тип &s[i] равен int (*)[2].

p - указатель на массив из 2 элементов int. Каждый раз в цикле p присваивается адрес массива из 2 элементов в s[i].

Наконец, pint - это простой указатель на int, и каждый раз в цикле устанавливается указатель на первый элемент в массиве, на который указывает p. *(pint + j) длинный путь написания pint[j].

Обратите внимание, что p и pint совершенно лишние ; в основном это многословный способ написания

for (i = 0; i < 4; i++)
{
  for (j = 0; j < 2; j++)
    printf("%d ", s[i][j]);
  printf("\n");
}
1 голос
/ 07 сентября 2011
#include <stdio.h>

int main(){
        int s[4][2] = {{1234,1},{1233,2},{1232,3},{1331,4}};
        int (*p)[2];
        int i,j,*pint;

        for(i=0;i<4;++i){
                p = &s[i];
                pint = (int*)p;
                printf("\n");
                for(j=0;j<=1;++j)
                        printf("%d ",*(pint+j));
        }
        return 0;
}

здесь p определяется как массив, который может хранить два целочисленных значения

 int (*p)[2];

во внешнем цикле for, мы используем массив p для хранения 4 {1-мерного}.1 за раз.

 p = &s[i];

, то есть в первой итерации это будет

p = &s[0] ;
i.e p = {1234,1}

, следующая итерация будет

 p = &s[1] ;
i.e p = {1234,2}

и так далее.вот почему нам нужен & S [i]

внутренний цикл, просто итерация по одномерному массиву для печати элемента

...