Синтаксис указателя на часть многомерного статически размещаемого массива - PullRequest
0 голосов
/ 25 августа 2010

Хорошо, у меня есть многомерный массив, который статически размещен. Я бы очень хотел получить указатель на его часть и использовать этот указатель для доступа к остальной части. По сути, я хотел бы иметь возможность сделать что-то вроде этого:

#include <stdio.h>
#include <string.h>

#define DIM1 4
#define DIM2 4
#define DIM3 8
#define DIM4 64

static char theArray[DIM1][DIM2][DIM3][DIM4] = {0};

int main()
{
    strcpy(theArray[0][0][0], "hello world");

    char** ptr = theArray[0][0];

    printf("%s\n", ptr[0]);

    return 0;
}s

Этот код приводит к этой ошибке, используя gcc:

t.c: In function ‘main’:
t.c:17: warning: initialization from incompatible pointer type

char**, по-видимому, неправильный тип для использования здесь. Я предполагаю, что это связано с тем, что статически размещенные массивы создаются как один блок в памяти, а динамически распределенные - в памяти, причем каждое измерение имеет указатель на следующий.

Однако, как вы, вероятно, заметили, число измерений здесь чрезвычайно велико, и мне, очевидно, потребуется использовать фактические переменные для индексации массива, а не красивый тонкий символ 0, поэтому он будет мучительно трудным долго индексировать массив в реальном коде. Я бы очень хотел иметь указатель на массив для использования, чтобы доступ к массиву был гораздо менее болезненным. Но я не могу понять правильный синтаксис - если таковой вообще есть. Таким образом, любая помощь будет оценена. Благодаря.

Ответы [ 4 ]

4 голосов
/ 25 августа 2010

С учетом декларации

T arr[J][K][L][M];

следующие все держатся:

     Expression            Type                    Decays to
     ----------            ----                    ---------
            arr            T [J][K][L][M]          T (*)[K][L][M]
           &arr            T (*)[J][K][L][M]
         arr[j]            T [K][L][M]             T (*)[L][M]
        &arr[j]            T (*)[K][L][M]
      arr[j][k]            T [L][M]                T (*)[M];
     &arr[j][k]            T (*)[L][M] 
   arr[j][k][l]            T [M]                   T *
  &arr[j][k][l]            T (*)[M]      

Итак, в вашем случае тип ptr должен быть char (*)[DIM4].

4 голосов
/ 25 августа 2010

theArray[0][0] избавляется от первых двух измерений, поэтому у вас есть что-то типа char [DIM3][DIM4].Первое измерение выпадает, когда массив распадается на указатель, поэтому объявление, которое вы хотите:

char (*ptr)[DIM4] = theArray[0][0];

Для чего бы то ни было, gcc также отображает предупреждение для вашего объявления массива: "warning: отсутствующие скобкивокруг инициализатора ".Статические переменные и глобальные переменные будут автоматически инициализированы равными 0, поэтому вы можете исправить предупреждение, избавившись от инициализатора:

static char theArray[DIM1][DIM2][DIM3][DIM4];
1 голос
/ 25 августа 2010

Если вы используете Visual Studio, хороший способ узнать тип выражения - использовать typeid.

cout << typeid(&theArray[0][0]).name();

который печатает

char (*) [8] [64]

Но обратите внимание, что вывод typeid (). Name () является поведением, специфичным для реализации, и на него нельзя полагаться. Но в этом отношении VS хорош, печатая более значимое имя

0 голосов
/ 25 августа 2010

Неважно, что оно статическое, ваши типы не совпадают

Почему двойной указатель нельзя использовать в качестве двумерного массива?

Это хороший пример, хотя компилятор может не жаловаться, неправильно объявлять: "int ** mat", а затем использовать "mat" в качестве 2D-массива. Это два очень разных типа данных, и с их помощью вы получаете доступ разные места в памяти. На хорошей машине (например, VAX / VMS) это ошибка завершает программу с ошибкой «нарушение доступа к памяти».

Эта ошибка встречается часто, потому что легко забыть, что распад соглашение не должно применяться рекурсивно (более одного раза) к тот же массив, поэтому двумерный массив НЕ эквивалентен двойному указателю.

«Указатель на указатель T» не может служить «2D-массивом T». 2D-массив "эквивалентен" указателю на строку T ", и это сильно отличается от «указатель на указатель T».

Когда двойной указатель указывает на первый элемент массива, используется с индексом «ptr [0] [0]», полностью разыменовывается два раза (см. правило № 5). После двух полных разыменований получающиеся Объект будет иметь адрес, равный любому значению, найденному ВНУТРИ первый элемент массива. Поскольку первый элемент содержит наши данные, мы бы имели дикий доступ к памяти. ...

и т.д .... http://www.ibiblio.org/pub/languages/fortran/append-c.html

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