Указатель на многомерный массив

Тема в разделе "LANGS.C", создана пользователем BlackParrot, 8 мар 2009.

  1. BlackParrot

    BlackParrot New Member

    Публикаций:
    0
    Регистрация:
    19 фев 2009
    Сообщения:
    163
    Привет всем. Простой вопрос, но он у меня вызвал сложности. Может быть я перегрелся.
    Пусть у нас есть многомерный массив. Например, такой:
    Код (Text):
    1. char* np_regs [10][6] =
    2. {
    3.     {   "BX+SI",    "BX+DI", "BP+SI",   "BP+DI",    "SI",    "DI",    "BP",    "BX"     },
    4.     {   "EAX",      "ECX",   "EDX",     "EBX",      "ESP",   "EBP",   "ESI",   "EDI"    },
    5.     {   "MM0",      "MM1",   "MM2",     "MM3",      "MM4",   "MM5",   "MM6",   "MM7"    },
    6.     {   "XMM0",     "XMM1",  "XMM2",    "XMM3",     "XMM4",  "XMM5",  "XMM6",  "XMM7"   },
    7.     {   "AL",       "CL",    "DL",      "BL",       "AH",    "CH",    "DH",    "BH"     },
    8.     {   "AX",       "CX",    "DX",      "BX",       "SP",    "BP",    "SI",    "DI"     },
    9.     {   "CR0",      "",  "CR2",     "CR3",      "CR4",   "",      "",      ""       },
    10.     {   "DR0",      "DR1",   "DR2",     "DR3",      "",      "",      "DR6",   "DR7"    },
    11.     {   "ES",       "CS",    "SS",      "DS",       "FS",    "GS",    "",      ""       },
    12.     {   "ST(0)",    "ST(1)", "ST(2)",   "ST(3)",    "ST(4)", "ST(5)", "ST(6)", "ST(7)"  }
    13. };
    В коде можно использовать обращение вида np_regs[1][1] - и это будет указатель на строку.
    Допустим мне захотелось передать в поток через параметр CreateThread этот массив. Ясно, что я буду передавать указатель. Но как описать указатель на этот массив, чтобы потом можно было также обращатся array_regs[1][1]??? Как мне кажется задача очень очевидная. Но решить я ее не могу. По просторам лазил - один бред пишут. Прошу помощи в общем. Пишу на Си, т.е. просьба ООП фичи не предлагать. Спасибо.
     
  2. BlackParrot

    BlackParrot New Member

    Публикаций:
    0
    Регистрация:
    19 фев 2009
    Сообщения:
    163
    И очевидно, что я не хочу использовать статическую переменную np_regs, нужно динамически все сделать.
     
  3. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    char ***array_regs;
     
  4. CyberManiac

    CyberManiac New Member

    Публикаций:
    0
    Регистрация:
    2 сен 2003
    Сообщения:
    2.473
    Адрес:
    Russia
    Опиши отдельно тип1 массива, сделай ещё один тип2 - указатель на предыдущий, а после всего - выдели кусок памяти sizeof(типа1), затолкай туда всё, что нужно, а укаазатель на этот кусок нехай будет типа2. А вот использовать грязные хаки типа "указатель на начало массива - это указатель на нулевой элемент" там, где они не нужны абсолютно, лучше не надо. Плохой стиль всегда следует оставлять плохим писателям.
     
  5. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    Грязные хаки, прописанные в стандарте?
     
  6. BlackParrot

    BlackParrot New Member

    Публикаций:
    0
    Регистрация:
    19 фев 2009
    Сообщения:
    163
    n0name
    Вот так я сделал сразу. И это не работает. Можете сами попробывать. Почему не работает сами знаете, объяснять лишняя трата времени.

    CyberManiac
    Если честно ничего не понял из вашего описания :) Код чтоли дайте или попонятнее растолкуйте. Не понял что такое "предыдущий".

    Вроде задача-то крайне чистая и очевидная. Но я так и не могу понять как сделать этот чертов указатель :) Ведь, если есть тип из стандартных типов данных ведь просто обязательно должна быть возможность иметь указатель на этот тип. Неужели надо складывать там эти состовляющие? Я лично через попу не хочу обращаться к элементам - сложением. И вот эта записть "(*((E1)+(E2)))" считаю ее крайне убожеской по стилю. Зачем ее использовать, если есть нормальный оператор "[]". Давайте вместе думать! :)
     
  7. BlackParrot

    BlackParrot New Member

    Публикаций:
    0
    Регистрация:
    19 фев 2009
    Сообщения:
    163
    Исправляю пример. Первая строка такая:
    Код (Text):
    1. char np_regs [][10][6] =
     
  8. BlackParrot

    BlackParrot New Member

    Публикаций:
    0
    Регистрация:
    19 фев 2009
    Сообщения:
    163
    Если это невозможно без асма и арифметики указателей, то скажите пожалуйста.
     
  9. BlackParrot

    BlackParrot New Member

    Публикаций:
    0
    Регистрация:
    19 фев 2009
    Сообщения:
    163
    Глупо, что в функции указатель передается без проблем, и потом можно его использовать. Т.е. в прологе функции этот указатель легко описывается. А что если этот указатель будет частью структуры? Как это реализовать????????
    Код (Text):
    1. int test_function(char x[][10][6])
    2. {
    3.     printf(x[0][5]);
    4.     return;
    5. }
    6.  
    7. test_function(np_regs);
     
  10. Ustus

    Ustus New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2005
    Сообщения:
    834
    Адрес:
    Харьков
    Что-то такое?
    Код (Text):
    1. void f(void* p)
    2. {
    3.    char*(* pm)[6] = static_cast<char*(*)[6]>(p);
    4.    pm[1][1];
    5. }
     
  11. BlackParrot

    BlackParrot New Member

    Публикаций:
    0
    Регистрация:
    19 фев 2009
    Сообщения:
    163
    Браво Ustus! Без вас бы не разобрался. Мне вот теперь интересно, что это за конструкция? Где она описана в книжках по языку? Я имею виду это обрамление в скобочки со звездочкой.
    Код (Text):
    1. char* (*pm)[6]
     
  12. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    BlackParrot
    Указатель на массив шести элементов, типа char*.
     
  13. BlackParrot

    BlackParrot New Member

    Публикаций:
    0
    Регистрация:
    19 фев 2009
    Сообщения:
    163
    Booster
    Если бы все было так просто - я бы не спрашивал. Вот скобочки уберешь из этой записи и все - уже ошибки будет изрыгиваться из рта компилятора. И почему так? В общем я сначала придумывал что-то подобное, но делал что-то подобное - char* (*)pm[6] - ведь это будет уже указатель на функцию. В общем все так так очевидно и думаю стоит надо этим поразмыслить. Хотя проблема для меня решена. Просто интересно почему это именно так записывается %)
     
  14. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    BlackParrot
    Ну поразмысли, только указатель на функцию объявляется иначе, например:void (*p)();

    А запись: char* (*pm)[6] - именно указатель на массив шести элементов, типа char*.
    К указателям тоже можно применять оператор квадратные скобки.
    int *p; p[10] = 0;
     
  15. _basmp_

    _basmp_ New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2005
    Сообщения:
    2.939
    тут по любому надо вручную присваивать. тк тип данных - указатели на строки, а под сами строки память выделять вручную надо. ведь они разные по длине. те делается локальная переменная типа
    char* np_regs [10][6];
    считывается очередная строчка, выделяется по ней память, копируется и присваивается элементу массива. или все сливается в один буфер, ищутся 0-ли и по ним присваиваются позиции в буфере. были б статичные по длине данные - было бы проще
     
  16. agrischuk

    agrischuk New Member

    Публикаций:
    0
    Регистрация:
    12 янв 2009
    Сообщения:
    47
    Называется pointer to array. Разжевывается в книжке Expert C Programming: Deep C Secrets, Peter van der Linden.
     
  17. Ustus

    Ustus New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2005
    Сообщения:
    834
    Адрес:
    Харьков
    BlackParrot
    Да легче сказать где она не описывается :) на самом деле все очень просто - модификатор описателя [] имеет более высокий приоритет, чем *, поэтому требуются скобки.
    char* x; - указатель
    char x[6] - массив
    char* x[6] - то же, что и char* (x[6]) - массив указателей
    char (*x)[6] - указатель на массив.
    Все просто, только требует некоторой привычки. А еще проще определить нужный тип через цепочку typedef. В данном случае, например так:
    Код (Text):
    1.      typedef char* array_str[6];
    2.      typedef array_str* array_ptr;
     
  18. BlackParrot

    BlackParrot New Member

    Публикаций:
    0
    Регистрация:
    19 фев 2009
    Сообщения:
    163
    В общем разобрался теперь :) Всем спасибо. Вот еще интересная ссылка по теме, там все раззжоввывается - http://home.netcom.com/~tjensen/ptr/ch8x.htm. Меня сбило с толку что в руссом интернете мне гугл ничего подобного не выдал :dntknw:
     
  19. Zitzy

    Zitzy New Member

    Публикаций:
    0
    Регистрация:
    4 янв 2009
    Сообщения:
    28
    А можно как-нибудь передать массив переменной размерности? Т.е. у меня есть несколько массивов вида table[5][], очень хочется в функции обращаться по индексам.
     
  20. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    #define COL 8
    вариант 1
    void show ( char *np_regs[], int rows ) {
    int i, j;
    for ( i = 0; i < rows; i++ ) {
    for ( j = 0; j < COL; j++ )
    printf ( "%s ", *(*(np_regs+i)+j) );
    //printf ( "%s ", np_regs[j] );
    putchar ( '\n' );
    }
    }
    вариант 2
    void show ( char *(*np_regs), int rows ) {
    int i, j;
    for ( i = 0; i < rows; i++ ) {
    for ( j = 0; j < COL; j++ )
    printf ( "%s ", *(*(np_regs+i)+j) );
    //printf ( "%s ", np_regs[j] );
    putchar ( '\n' );
    }
    }
    вариант 3
    void show ( char * p, int rows ) {
    int i, j;
    char*(*np_regs)=(char*(*))p;
    for ( i = 0; i < rows; i++ ) {
    for ( j = 0; j < COL; j++ )
    printf ( "%s ", *(*(np_regs+i)+j) );
    //printf ( "%s ", np_regs[j] );
    putchar ( '\n' );
    }
    }
    call show ( (char*)*np_regs, sizeof np_regs / sizeof *np_regs );
    вариант 4
    void show ( int p, int rows ) {
    int i, j;
    char*(*np_regs)=(char*(*))p;
    for ( i = 0; i < rows; i++ ) {
    for ( j = 0; j < COL; j++ )
    printf ( "%s ", *(*(np_regs+i)+j) );
    //printf ( "%s ", np_regs[j] );
    putchar ( '\n' );
    }
    }
    call show ( (int)*np_regs, sizeof np_regs / sizeof *np_regs );
    вариант 5
    void show ( char *** p , int rows ) {
    int i, j;
    char*(*np_regs)=(char*(*))p;
    for ( i = 0; i < rows; i++ ) {
    for ( j = 0; j < COL; j++ )
    printf ( "%s ", *(*(np_regs+i)+j) );
    //printf ( "%s ", np_regs[j] );
    putchar ( '\n' );
    }
    }
    call show ( (char***)*np_regs, sizeof np_regs / sizeof *np_regs );

    какая разница указатель на какой тип вы передаете можно написать в прототипе хоть указатель на слона главное закастить указатель правильно чтоб компилятор смещения высчитал )) и да главное чтоб была известа младшая размерность чтоб нам правильно указатель закастить нам могут передавать что угодно но мы должны это закастить в указатель на массив из N элементов
    указателей на char* если желаем просто писать np_regs[j]