Привет всем. Простой вопрос, но он у меня вызвал сложности. Может быть я перегрелся. Пусть у нас есть многомерный массив. Например, такой: Код (Text): char* np_regs [10][6] = { { "BX+SI", "BX+DI", "BP+SI", "BP+DI", "SI", "DI", "BP", "BX" }, { "EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI" }, { "MM0", "MM1", "MM2", "MM3", "MM4", "MM5", "MM6", "MM7" }, { "XMM0", "XMM1", "XMM2", "XMM3", "XMM4", "XMM5", "XMM6", "XMM7" }, { "AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH" }, { "AX", "CX", "DX", "BX", "SP", "BP", "SI", "DI" }, { "CR0", "", "CR2", "CR3", "CR4", "", "", "" }, { "DR0", "DR1", "DR2", "DR3", "", "", "DR6", "DR7" }, { "ES", "CS", "SS", "DS", "FS", "GS", "", "" }, { "ST(0)", "ST(1)", "ST(2)", "ST(3)", "ST(4)", "ST(5)", "ST(6)", "ST(7)" } }; В коде можно использовать обращение вида np_regs[1][1] - и это будет указатель на строку. Допустим мне захотелось передать в поток через параметр CreateThread этот массив. Ясно, что я буду передавать указатель. Но как описать указатель на этот массив, чтобы потом можно было также обращатся array_regs[1][1]??? Как мне кажется задача очень очевидная. Но решить я ее не могу. По просторам лазил - один бред пишут. Прошу помощи в общем. Пишу на Си, т.е. просьба ООП фичи не предлагать. Спасибо.
И очевидно, что я не хочу использовать статическую переменную np_regs, нужно динамически все сделать.
Опиши отдельно тип1 массива, сделай ещё один тип2 - указатель на предыдущий, а после всего - выдели кусок памяти sizeof(типа1), затолкай туда всё, что нужно, а укаазатель на этот кусок нехай будет типа2. А вот использовать грязные хаки типа "указатель на начало массива - это указатель на нулевой элемент" там, где они не нужны абсолютно, лучше не надо. Плохой стиль всегда следует оставлять плохим писателям.
n0name Вот так я сделал сразу. И это не работает. Можете сами попробывать. Почему не работает сами знаете, объяснять лишняя трата времени. CyberManiac Если честно ничего не понял из вашего описания Код чтоли дайте или попонятнее растолкуйте. Не понял что такое "предыдущий". Вроде задача-то крайне чистая и очевидная. Но я так и не могу понять как сделать этот чертов указатель Ведь, если есть тип из стандартных типов данных ведь просто обязательно должна быть возможность иметь указатель на этот тип. Неужели надо складывать там эти состовляющие? Я лично через попу не хочу обращаться к элементам - сложением. И вот эта записть "(*((E1)+(E2)))" считаю ее крайне убожеской по стилю. Зачем ее использовать, если есть нормальный оператор "[]". Давайте вместе думать!
Глупо, что в функции указатель передается без проблем, и потом можно его использовать. Т.е. в прологе функции этот указатель легко описывается. А что если этот указатель будет частью структуры? Как это реализовать???????? Код (Text): int test_function(char x[][10][6]) { printf(x[0][5]); return; } test_function(np_regs);
Что-то такое? Код (Text): void f(void* p) { char*(* pm)[6] = static_cast<char*(*)[6]>(p); pm[1][1]; }
Браво Ustus! Без вас бы не разобрался. Мне вот теперь интересно, что это за конструкция? Где она описана в книжках по языку? Я имею виду это обрамление в скобочки со звездочкой. Код (Text): char* (*pm)[6]
Booster Если бы все было так просто - я бы не спрашивал. Вот скобочки уберешь из этой записи и все - уже ошибки будет изрыгиваться из рта компилятора. И почему так? В общем я сначала придумывал что-то подобное, но делал что-то подобное - char* (*)pm[6] - ведь это будет уже указатель на функцию. В общем все так так очевидно и думаю стоит надо этим поразмыслить. Хотя проблема для меня решена. Просто интересно почему это именно так записывается %)
BlackParrot Ну поразмысли, только указатель на функцию объявляется иначе, например:void (*p)(); А запись: char* (*pm)[6] - именно указатель на массив шести элементов, типа char*. К указателям тоже можно применять оператор квадратные скобки. int *p; p[10] = 0;
тут по любому надо вручную присваивать. тк тип данных - указатели на строки, а под сами строки память выделять вручную надо. ведь они разные по длине. те делается локальная переменная типа char* np_regs [10][6]; считывается очередная строчка, выделяется по ней память, копируется и присваивается элементу массива. или все сливается в один буфер, ищутся 0-ли и по ним присваиваются позиции в буфере. были б статичные по длине данные - было бы проще
Называется pointer to array. Разжевывается в книжке Expert C Programming: Deep C Secrets, Peter van der Linden.
BlackParrot Да легче сказать где она не описывается на самом деле все очень просто - модификатор описателя [] имеет более высокий приоритет, чем *, поэтому требуются скобки. char* x; - указатель char x[6] - массив char* x[6] - то же, что и char* (x[6]) - массив указателей char (*x)[6] - указатель на массив. Все просто, только требует некоторой привычки. А еще проще определить нужный тип через цепочку typedef. В данном случае, например так: Код (Text): typedef char* array_str[6]; typedef array_str* array_ptr;
В общем разобрался теперь Всем спасибо. Вот еще интересная ссылка по теме, там все раззжоввывается - http://home.netcom.com/~tjensen/ptr/ch8x.htm. Меня сбило с толку что в руссом интернете мне гугл ничего подобного не выдал
А можно как-нибудь передать массив переменной размерности? Т.е. у меня есть несколько массивов вида table[5][], очень хочется в функции обращаться по индексам.
#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]