реклама на сайте
подробности

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


Профессионал
*****

Группа: Свой
Сообщений: 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 **"
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
XVR
сообщение Jun 10 2009, 09:34
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847



Открою великую тайну rolleyes.gif - как сделать из массива (любого) тип, который можно будет написать в параметрах функции (например).
Берем исходное определение переменной -
Код
unsigned int __flash Program1[5][4] = {...}

Меняем имя переменной на тип, удаляем = и всё после него и пишем typedef вначале, все
Код
typedef unsigned int __flash ProgramType[5][4];

Используем
Код
void func(ProgramType my_var) {...}
Go to the top of the page
 
+Quote Post
defunct
сообщение Jun 14 2009, 03:07
Сообщение #3


кекс
******

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



Цитата(XVR @ Jun 10 2009, 12:34) *
Открою великую тайну rolleyes.gif - как сделать из массива (любого) тип, который можно будет написать в параметрах функции (например).

еще проще - написать по вкусу 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 ] );
Go to the top of the page
 
+Quote Post
Wano
сообщение Jun 14 2009, 09:16
Сообщение #4


Местный
***

Группа: Свой
Сообщений: 272
Регистрация: 3-06-06
Пользователь №: 17 737



не рычите люди. С тем, что через void* можно бросить указатель в функцию хоть слона это ясно, искать маркер конца строк массива тоже ясно(один чёрт оно и так всё в ряд). Дайте ответ на вопрос:
Можно ли элементарно преобразовать указатель чего угодно, переданный в функцию, к виду [][] , а не работать со сдвигами? Зная размерность. И не трогать при это с++.
С чего угодно малость загнул, хотябы разобраться с char.
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Jun 14 2009, 09:39
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



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

Сдвиги то откуда взялись?
И вообще - Вам шашечки (двумерный массив) или ехать (управление по программе).
Если все-таки ехать, то defunct все подробно описал, когда я поленился.


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
Wano
сообщение Jun 14 2009, 10:04
Сообщение #6


Местный
***

Группа: Свой
Сообщений: 272
Регистрация: 3-06-06
Пользователь №: 17 737



Конкретней : получаем в функции указатель:
void func(void *temp)
создаём указатель на нужный объект, char :
char * c_Uk;
связываем:
c_Uk= (char *)temp;
Вопрос: почему, если :
*(c_Uk+2)=5;
и
c_Uk[2]=5;
синонимы, то не проходят коснтрукции типа
c_Uk[1][1]=5;
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jun 14 2009, 10:16
Сообщение #7


Гуру
******

Группа: Модераторы
Сообщений: 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)
Go to the top of the page
 
+Quote Post
Wano
сообщение Jun 14 2009, 10:34
Сообщение #8


Местный
***

Группа: Свой
Сообщений: 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;
}

если забить на лишние указатели,то не плохо. Всем спасибо.
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Jun 14 2009, 10:51
Сообщение #9


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



Цитата(Wano @ Jun 14 2009, 14:34) *
если забить на лишние указатели,то не плохо. Всем спасибо.


Жуть, что вы тут понаписали.
Go to the top of the page
 
+Quote Post
Wano
сообщение Jun 14 2009, 10:56
Сообщение #10


Местный
***

Группа: Свой
Сообщений: 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;
}
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jun 14 2009, 11:33
Сообщение #11


Гуру
******

Группа: Модераторы
Сообщений: 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)
Go to the top of the page
 
+Quote Post
Wano
сообщение Jun 14 2009, 12:48
Сообщение #12


Местный
***

Группа: Свой
Сообщений: 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 *"
вот и пошла фонтазия художника smile.gif
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jun 14 2009, 16:33
Сообщение #13


Гуру
******

Группа: Модераторы
Сообщений: 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)
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- 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


Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 23rd June 2025 - 15:19
Рейтинг@Mail.ru


Страница сгенерированна за 0.01544 секунд с 7
ELECTRONIX ©2004-2016