|
Двумерный массив и указатель на него, Как объявить чтобы можно было обращаться massiv[x][y]? |
|
|
|
Jun 9 2009, 12:23
|

Профессионал
    
Группа: Свой
Сообщений: 1 001
Регистрация: 27-06-06
Пользователь №: 18 409

|
Добрый день. Чтото не могу понять как правильно объявить указатель на двумерный массив чтобы компилятор не ругался. Есть такой массив: Код [b]unsigned int [/b] [i]__flash[/i] Program1[5][4] = { {0,0,0,0}, {1,1,1,1}, {2,2,2,2}, {3,3,3,3}, {4,4,4,4} } И есть некая структура управления в которой хочу создать указатель на этот двумерный массив: Код typedef struct { unsigned int __flash **program;//указатель на текущую исполняемую программу } stProgram;
stProgram Program; //экземпляр структуры Стоит задача сделать так чтобы используя указатель Program.program обращаться к двумерному массиву наиболее понятным образом Program.program[0][1] (без использования * и всяких смещений) Определил функцию инициализации масива Код void SetProgram(unsigned int __flash **program_addr) { Program.program = program_addr; } Компилятор ругается на вызов этой функции: Код SetProgram(&Program1[0][0]); Цитата Error[Pe167]: argument of type "unsigned int __flash (*)[4]" is incompatible with parameter of type "unsigned int __flash **"
|
|
|
|
|
 |
Ответов
|
Jun 10 2009, 09:34
|
Гуру
     
Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847

|
Открою великую тайну  - как сделать из массива (любого) тип, который можно будет написать в параметрах функции (например). Берем исходное определение переменной - Код unsigned int __flash Program1[5][4] = {...} Меняем имя переменной на тип, удаляем = и всё после него и пишем typedef вначале, все Код typedef unsigned int __flash ProgramType[5][4]; Используем Код void func(ProgramType my_var) {...}
|
|
|
|
|
Jun 14 2009, 03:07
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(XVR @ Jun 10 2009, 12:34)  Открою великую тайну  - как сделать из массива (любого) тип, который можно будет написать в параметрах функции (например). еще проще - написать по вкусу PVOID или PCHAR Цитата(sergeeff @ Jun 14 2009, 03:16)  Не очень изящно на С получается, перейдите на С++, сделайте себе объект - n-мерный массив (примеров - полно), Не будет изящной реализации на любом языке, когда выбран КРИВОЙ алгоритм решения задачи изначально. описать действия можно и в одномерном массиве, причем прекрасно читаемо: Код int Program_1[] = { /* step1 */ 1, 1, 1, 1, 1, 1, 1, 0, /* step2 */ 2, 2, 2, 0, /* step3 */ 3, 3, 3, 3, 3, 0, /* step4 */ 4, 4, 4, 4, 4, 0, /* step5 */ 5, 5, 0, /* end */ 0 };
int Program_2[] = { /* step1 */ 11, 11, 11, 0, /* step2 */ 44, 44, 44, 44, 0, /* end */ 0 };
int *Programs[] = { Program_1, Program_2 ... }; ; где каждый "step" может быть любой длины и отделен от остальных 0-терминатором. конец программы - step начинающийся с терминатора. далее пишем функцию для поиска очередного "step'a": Код int *FindStep( int *program, int StepId ) { if (!*program) return NULL;
while (StepId) { if (!*program++) if (!*program) return NULL; else StepId--; } return program; } Ну а потом уже и DoProgram c DoStep'ом Код DoStep( int *step) { while( *step ) { ... // делаем что надо step++ } }
DoProgram( int *program) { do { DoStep( program ) } while ( program = FindStep( program, 1 ) ); } работаем с этим как: DoProgram( Programs[ x ] );
|
|
|
|
|
Jun 14 2009, 09:39
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(Wano @ Jun 14 2009, 12:16)  ...Дайте ответ на вопрос: Можно ли элементарно преобразовать указатель чего угодно, переданный в функцию, к виду [][] , а не работать со сдвигами? Зная размерность. И не трогать при это с++. ... Сдвиги то откуда взялись? И вообще - Вам шашечки (двумерный массив) или ехать (управление по программе). Если все-таки ехать, то defunct все подробно описал, когда я поленился.
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Jun 14 2009, 10:16
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(Wano @ Jun 14 2009, 13:04)  то не проходят коснтрукции типа c_Uk[1][1]=5; Потому что c_Uk - указатель, из которого можно получить лишь одномерный массив. Вы не сообщили компилятору размер строки, а хотите от него получить адрес по формуле: номер строки * размер строки + номер столбца. Попробуйте сами написать формулу, которую компилятор должен подставить для вычисления адреса элемента c_Uk[1][1]. Если вы хотите обращаться с c_Uk как с двумерным массивом, то и объявляйте его как указатель на двумерный массив. Но при этом вам надо отдавать себе отчет, что правила языка С89 требуют, чтобы одно из измерений такого массива было фиксировано на этапе компиляции. Если вам надо внутри функции работать с массивом, в котором оба измерения неизвестны на этапе компиляции - вам прямой путь или в С99 (как показал ReAl), или в адресную арифметику. Т.е. сначала вручную находите адрес нужной вам строки, потом с этой строкой можете работать как с одномерным массивом или как с указателем.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jun 14 2009, 10:34
|
Местный
  
Группа: Свой
Сообщений: 272
Регистрация: 3-06-06
Пользователь №: 17 737

|
Цитата(Сергей Борщ @ Jun 14 2009, 13:16)  Т.е. сначала вручную находите адрес нужной вам строки, потом с этой строкой можете работать как с одномерным массивом или как с указателем. void func(void *temp){//для массива 5х5 char * c_Uk[20]; c_Uk[0]= (char *)temp; c_Uk[1]= c_Uk[0]+5; c_Uk[2]= c_Uk[1]+5; c_Uk[3]= c_Uk[2]+5; c_Uk[4]= c_Uk[3]+5; c_Uk[2][2]=5; } если забить на лишние указатели,то не плохо. Всем спасибо.
|
|
|
|
|
Jun 14 2009, 10:56
|
Местный
  
Группа: Свой
Сообщений: 272
Регистрация: 3-06-06
Пользователь №: 17 737

|
Цитата(sergeeff @ Jun 14 2009, 13:51)  Жуть, что вы тут понаписали. как посоветовали, образно прикинул начала строк, присвоил их адреса к элементам массива указателей, в котором есть уже одна размерность. Что не так? Ясно что нужно ещё передавать размерность в функцию и грамотно расписать. char array[5][5]; void func(void *temp,char x,char y){ char * c_Uk[20];//заранее больше одной размерности char i; c_Uk[0]= (char *)temp; for(i=1;i<y;i++){ c_Uk[i]=c_Uk[i-1]+x; } c_Uk[1][2]=5; } int main (void) { func(&array[0][0],5,5); return 0; }
|
|
|
|
|
Jun 14 2009, 11:33
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(Wano @ Jun 14 2009, 13:56)  как посоветовали, образно прикинул начала строк, присвоил их адреса к элементам массива указателей, в котором есть уже одна размерность. Что не так? Мама!!! "Не так" - реализация. Я не понял, что должна делать ваша функция, поэтому в качестве примера просто прохожу по всему массиву и присваиваю элементам константу 1: Код #include <stdint.h> uint8_t array[5][5]; // у вас ведь массив не символов а именно беззнаковых 8-битных чисел
void func(uint8_t *temp, uint8_t x, uint8_t y) // temp именно указатель на uint8_t, а ни в коем случае не на на void, чтобы случайно не передать в функцию чего попало. Тип, на который указывает temp определяет размер элемента массива и этот размер дальше учитывается в адресной арифметике. { uint8_t *c_Uk; // размерность неизвестна, поэтому просто указатель uint8_t i; for(i = 0; i < y; ++i) // перебор строк массива { c_Uk = &temp[i * x]; // находим в линейном массиве temp адрес, с которого начинается i-я строка размером x. // c_Uk = temp + i * x; // то же самое другими словами // теперь c_Uk указывает на строку двумерного массива uint8_t j; for(j = 0; j < x; ++j) // проходим по строке { c_Uk[j] = 1; } } // "Дембельский" аккорд c_Uk = &temp[2 * x]; // вторая строка c_UK[1] = 5; // первый элемент в строке. т.е. массив[1][2] = 5 }
int main (void) { func(array // имя массива есть указатель на его нулевой элемент. Поэтому & и [0][0] не нужны. ,sizeof(array[0]) / sizeof(array[0][0]) // размерность x ,sizeof(array) / sizeof(array[0]) // размерность y ); return 0; } А книжку все же почитайте. Как только поймете, что такое указатель - сразу все станет просто.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jun 14 2009, 12:48
|
Местный
  
Группа: Свой
Сообщений: 272
Регистрация: 3-06-06
Пользователь №: 17 737

|
Ладно шариться по массиву можно хорошо и так: void func(char *temp,char x,char y){ int i,j; for(i=0;i<y;i++)//по столбцам for(j=0;j<x;j++){//по строкам *(temp+i*y+j)=1; } } и ещё кучей способов. мне хотелось именно квадратные скобки, дабы повысить наглядность коэффициентов при расчёте определителей матрицы. Определитель матрицы 5х5 , выполненный сначало на индексах - и начинает рябить.И чем больше, тем труднее ошибку в индексе найти. А огород из void , & и [0][0] начал городить из-за того, что uint8_t array[5][5]; void func(uint8_t *temp, uint8_t x, uint8_t y){.......} func(array ,sizeof(array[0]) / sizeof(array[0][0]),sizeof(array) / sizeof(array[0])); вызывает ошибку компилера RV: main.c(28): error: #167: argument of type "char (*)[5]" is incompatible with parameter of type "char *" вот и пошла фонтазия художника
|
|
|
|
|
Jun 14 2009, 16:33
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(Wano @ Jun 14 2009, 15:48)  мне хотелось именно квадратные скобки, дабы повысить наглядность коэффициентов при расчёте определителей матрицы. Определитель матрицы 5х5 , выполненный сначало на индексах - и начинает рябить. Если размерность массива неизвестна на этапе компиляции - то только С99 или плюсы. В С89 с квадратными скобками - невозможно. Вам это пытаются объяснить уже 4 страницы. Если размерность известна - то можно и в С89, но тогда нафига ее (размерность) передавать в качестве парметров в функцию? Цитата(Wano @ Jun 14 2009, 15:48)  вызывает ошибку компилера RV: Да, тут я фигню спопрол. ReAl уже поправил.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
Сообщений в этой теме
mempfis_ Двумерный массив и указатель на него Jun 9 2009, 12:23 777777 Цитата(mempfis_ @ Jun 9 2009, 16:23) unsi... Jun 9 2009, 12:33 zltigo Цитата(mempfis_ @ Jun 9 2009, 15:23) Чтот... Jun 9 2009, 12:43 mempfis_ Хорошо предположим я объявлю функцию с указателем ... Jun 9 2009, 12:56  MrYuran Цитата(mempfis_ @ Jun 9 2009, 16:56) Как ... Jun 9 2009, 13:03   mempfis_ ЦитатаТак прямо так и обращаться.
Program.program[... Jun 9 2009, 13:23    zltigo Цитата(mempfis_ @ Jun 9 2009, 16:23) комп... Jun 9 2009, 13:27    defunct Цитата(mempfis_ @ Jun 9 2009, 16:23) Так ... Jun 9 2009, 14:29 Goodefine А чего бы в таком виде не сделать:
Кодvalue_from_a... Jun 9 2009, 13:35 mempfis_ Цитата(Goodefine @ Jun 9 2009, 16:35) А ч... Jun 9 2009, 13:46  zltigo Цитата(mempfis_ @ Jun 9 2009, 16:46) К со... Jun 9 2009, 14:23 Goodefine Цитата(mempfis_ @ Jun 9 2009, 16:46) да и... Jun 9 2009, 13:50 mempfis_ КодВы сможете на плюсах. В обычном Си компиляторе ... Jun 9 2009, 13:58 Goodefine Цитата(zltigo @ Jun 9 2009, 17:23) Глупос... Jun 9 2009, 14:34 zltigo Цитата(Goodefine @ Jun 9 2009, 17:34) и Р... Jun 9 2009, 14:39  demiurg_spb Вопрошающему: посторайтесь понять это и Вы найдёте... Jun 9 2009, 15:59   defunct Цитата(demiurg_spb @ Jun 9 2009, 18:59) t... Jun 9 2009, 18:32    demiurg_spb Цитата(defunct @ Jun 9 2009, 22:32) нам н... Jun 9 2009, 19:31     defunct Цитата(demiurg_spb @ Jun 9 2009, 22:31) Д... Jun 9 2009, 21:23 Goodefine Я к тому, что решение проблемы автора при обращен... Jun 9 2009, 14:42 zltigo Цитата(Goodefine @ Jun 9 2009, 17:42) Я ... Jun 9 2009, 14:58 sergeeff Уважаемый коллега zltigo привел пример не совсем т... Jun 9 2009, 16:19 demiurg_spb Простите, но зачем городить структуру? Автор спраш... Jun 9 2009, 16:31  Dog Pawlowa Цитата(demiurg_spb @ Jun 9 2009, 19:31) А... Jun 9 2009, 16:58   demiurg_spb Цитата(Dog Pawlowa @ Jun 9 2009, 20:58) .... Jun 9 2009, 18:09  zltigo Цитата(demiurg_spb @ Jun 9 2009, 19:31) П... Jun 9 2009, 17:26 mempfis_ name=' date='Jun 9 2009, 19:19' post=... Jun 10 2009, 08:36  zltigo Цитата(mempfis_ @ Jun 10 2009, 11:36) Пер... Jun 10 2009, 09:16  Dog Pawlowa Цитата(mempfis_ @ Jun 10 2009, 11:36) Но ... Jun 10 2009, 09:19  ReAl Цитата(mempfis_ @ Jun 10 2009, 11:36) Во-... Jun 10 2009, 10:23   Wano ЫЫЫЫЫ чего-то не катит
typedef char TypeD[5][5]... Jun 13 2009, 21:13    AHTOXA Цитата(Wano @ Jun 14 2009, 03:13) ЫЫЫЫЫ ч... Jun 13 2009, 21:21    ReAl RE: Двумерный массив и указатель на него Jun 13 2009, 23:07     Wano Кодvoid func( unsigned size_y, unsigned size_x... Jun 13 2009, 23:44    XVR Цитата(Wano @ Jun 14 2009, 01:13) ЫЫЫЫЫ ч... Jun 15 2009, 09:18     sergeeff Цитата(XVR @ Jun 15 2009, 12:18) Мдя. Вы ... Jun 15 2009, 09:24      AHTOXA Цитата(sergeeff @ Jun 15 2009, 15:24) Зат... Jun 15 2009, 09:54     AHTOXA Цитата(Wano @ Jun 14 2009, 16:04) Вопрос:... Jun 14 2009, 10:12      sergeeff Цитата(AHTOXA @ Jun 14 2009, 14:12) Потом... Jun 14 2009, 10:31         sergeeff Цитата(Wano @ Jun 14 2009, 14:56) как пос... Jun 14 2009, 11:11           ReAl Цитата(Wano @ Jun 14 2009, 15:48) uint8_t... Jun 14 2009, 14:20            aaarrr Цитата(ReAl @ Jun 14 2009, 18:20) По пово... Jun 14 2009, 16:07 sergeeff Да, блин! Все рассказали, объяснили, примеры п... Jun 14 2009, 00:16 sergeeff Не хочет народ читать книги отцов-основателей.
Дл... Jun 14 2009, 10:08
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|