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

 
 
> Двумерный массив и указатель на него, Как объявить чтобы можно было обращаться 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
Ответов
sergeeff
сообщение Jun 9 2009, 16:19
Сообщение #2


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

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



Уважаемый коллега zltigo привел пример не совсем того, про что спрашивал автор топика. Он ведь хотел иметь внутри структуры указатель на двумерный массив.

Посему, привожу изменненный вариант:

Код
typedef struct {
int (*pdm)[8];
} dm_t;

int dm[8][8];

int test(dm_t *dm_ptr)
{
   printf("size pdm = %d\n", sizeof(dm_ptr->pdm));
   return(dm_ptr->pdm[3][3] );
}

dm_t  mm;
int main(int argc, char *argv[])
{
     int i = 8;
     dm[3][3] = 5;
     mm.pdm = &dm[8];
     i = test(&mm);
     printf("i = %d\n", i);
     return 1;
}
Go to the top of the page
 
+Quote Post
mempfis_
сообщение Jun 10 2009, 08:36
Сообщение #3


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

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



name=' date='Jun 9 2009, 19:19' post='604857'

Спасибо sergeeff, ваш вариант именно то что я хотел получить.
Переделал его на свой лад. Получилось то что написано ниже.

Код
#define max_size 5
unsigned int __flash Program1[max_size][4]=
{
   {1,1,1,1},
   {2,2,2,2},
   {3,3,3,3}
};

//массив второй программы из 5ти действий
unsigned int __flash Program2[max_size][4]=
{
   {7,7,7,7},
   {8,8,8,8},
   {9,9,9,9},
   {11,11,11,11},
   {44,44,44,44}
};

//структура управления программой
typedef struct {
unsigned int __flash (*program)[max_size];
} stProgram;

stProgram Program;

//процедура инициализации структуры управления
void SetProgram(unsigned int __flash (*addr)[])
{
  Program.program = addr;
}


void main(void)
{
//настройка программы
SetProgram(&Program1[0]);

//основной цикл программы
for(;;);
}


Теперь можно обращаться к элементам программы через указатель Program.program просто переберая индексы
Program.program[1][0], Program.program[2][1] и т.д.

Но есть ньюансы.
Во-первых размер возможных программ всегда должен быть максимальный (max_size).
Во-вторых код компилируется только в режиме С.
В режиме Embedded C++ выскакивает ошибка на процедуру инициализации программы
Код
void SetProgram(unsigned int __flash (*addr)[])
Error[Pe615]: parameter type involves pointer to array of unknown bound
Go to the top of the page
 
+Quote Post
ReAl
сообщение Jun 10 2009, 10:23
Сообщение #4


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(mempfis_ @ Jun 10 2009, 11:36) *
Во-первых размер возможных программ всегда должен быть максимальный (max_size).
Во-вторых код компилируется только в режиме С.

И первое и второе неверно.
Код
#include <iostream>

unsigned int Program1[][4]=
{
   {1,1,1,1},
   {2,2,2,2},
   {3,3,3,3}
};

unsigned int Program2[][4]=
{
   {7,7,7,7},
   {8,8,8,8},
   {9,9,9,9},
   {11,11,11,11},
   {44,44,44,44}
};


void foo( const char *header, unsigned int pgm[][4], int size)
{
    std::cout << "======== " << header << "[" << size << "]" << std::endl;
    for( int i=0; i < size; ++i)
        std::cout << pgm[i][0] << ", " << pgm[i][1] << ", " << pgm[i][2] << ", " << pgm[i][3] << std::endl;
    std::cout << std::endl;
}

#define CALL_FOO(array) foo( #array, array, sizeof(array) / sizeof(array[0]) )

int main()
{
    CALL_FOO(Program1);
    CALL_FOO(Program2);
}

Код
gcc -Os -s foo.cpp -o foo.exe
foo.exe >foo.txt

Код
======== Program1[3]
1, 1, 1, 1
2, 2, 2, 2
3, 3, 3, 3

======== Program2[5]
7, 7, 7, 7
8, 8, 8, 8
9, 9, 9, 9
11, 11, 11, 11
44, 44, 44, 44


В смысле размер может быть переменным, но его надо или отдельно передать, или ограничить признаком, скажем, в реальной программе не бывает отрицательных чисел, тогда так
Код
unsigned int Program2[][4]=
{
   {7,7,7,7},
   {8,8,8,8},
   {9,9,9,9},
   {11,11,11,11},
   {44,44,44,44},
   {-1,-1,-1,-1}  // ограничитель и в цикле идти до него, а не по счётчику
};


Кстати, прототип функции С/С++ воспринимают как
Код
void foo(const char*, unsigned int (*)[4], int)

т.е. как функцию, принимающую указатель на 4-интовые массивы.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
Wano
сообщение Jun 13 2009, 21:13
Сообщение #5


Местный
***

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



ЫЫЫЫЫ чего-то не катит

typedef char TypeD[5][5];

char array[5][5];

void func(TypeD * temp){
*temp[1][0]=5;//лезет не в &array+5 ,а в &array+25
}

int main (void)
{
func(&array);
return 0;
}

В disassembly видно что забит сдвиг от начала массива не на пять байт ,а на 25. Всё щастье пашет только на диапазоне *temp[0][0]....*temp[0][4] sad.gif
Go to the top of the page
 
+Quote Post
ReAl
сообщение Jun 13 2009, 23:07
Сообщение #6


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(Wano @ Jun 14 2009, 00:13) *
ЫЫЫЫЫ чего-то не катит

typedef char TypeD[5][5];

char array[5][5];

void func(TypeD * temp){
...
В disassembly видно что забит сдвиг от начала массива не на пять байт ,а на 25. Всё щастье пашет только на диапазоне *temp[0][0]....*temp[0][4] sad.gif
Естественно.
temp объявлен как указатель на массив char[5][5]
Соответственно temp[1] - это следующий такой массив (temp[1] есть массив char[5][5]), temp[1][0] - первый его подмассив, *temp[1][0], рассматриваемый как *(temp[1][0]) (приоритеты операций в С желательно выучить до начала программирования) - это нулевой элемент данного подмассива.
То, чего Вы хотите, можно достичь двумя способами
Код
typedef char TypeD[5][5];

void func_1(TypeD *temp){
    (*temp)[1][0]=5;
}

void func_2(TypeD temp){
    temp[1][0]=5;
}

Код
    .text
.global    func_1
    .type    func_1, @function
func_1:
/* prologue: frame size=0 */
/* prologue end (size=0) */
    ldi r18,lo8(5)
    movw r30,r24
    std Z+5,r18
/* epilogue: frame size=0 */
    ret
/* epilogue end (size=1) */
/* function func_1 size 4 (3) */
    .size    func_1, .-func_1

.global    func_2
    .type    func_2, @function
func_2:
/* prologue: frame size=0 */
/* prologue end (size=0) */
    ldi r18,lo8(5)
    movw r30,r24
    std Z+5,r18
/* epilogue: frame size=0 */
    ret
/* epilogue end (size=1) */
/* function func_2 size 4 (3) */
причём в первом я не вижу никакого смысла.

Ну а как бы я делал это (точнее, как я уже это делал) - я изобразил в предыдущем своём сообщении.

Кстати, С99 позволяет вообще так:
Код
void func( unsigned size_y, unsigned size_x, char array[size_y][size_x] )
{
    array[2][1] = 'a';
}

Код
    .text
.global    func
    .type    func, @function
func:
/* prologue: frame size=0 */
/* prologue end (size=0) */
    movw r30,r22
    lsl r30
    rol r31
    add r30,r20
    adc r31,r21
    ldi r24,lo8(97)
    std Z+1,r24
/* epilogue: frame size=0 */
    ret
/* epilogue end (size=1) */
/* function func size 8 (7) */
    .size    func, .-func

Только, хоть и прошло уже десять лет, не все компиляторы поддерживают все возможности С99.


И ещё вдогонку.

Массивов в языке С... Ну не так, чтобы нету совсем, но и что есть сказать тяжело.

Есть указатели и развитая арифметика с ними. Есть некий "макрос" из квадратных скобок, который облегчает запись этой арифметики. Именно поэтому функции в "можно достичь двумя способами" выше имеют тождественный код и хоть и должны вызывться по разному на уровне исходника
Код
void func_3()
{
    func_1( &array);
    func_2( array);
}
но код вызова тоже тождественный
Код
.global    func_3
    .type    func_3, @function
func_3:
/* prologue: frame size=0 */
    push r16
    push r17
/* prologue end (size=2) */
    ldi r16,lo8(array)
    ldi r17,hi8(array)
    movw r24,r16
    rcall func_1
    movw r24,r16
    rcall func_2
/* epilogue: frame size=0 */
    pop r17
    pop r16
    ret
/* epilogue end (size=3) */
/* function func_3 size 11 (6) */
    .size    func_3, .-func_3


Более того (специально сделал элемент массива двухбайтовым, чтобі біло чётко видно, что множится на два всегда "истинный" индекс, даже если он стоит перед скобками):
Код
unsigned a[5];

unsigned func_1(unsigned char i)
{
    return a[i];
}

unsigned func_2(unsigned char i)
{
    return i[a];
}

Код
.global    func_1
    .type    func_1, @function
func_1:
    mov r30,r24
    ldi r31,lo8(0)
    lsl r30
    rol r31
    subi r30,lo8(-(a))
    sbci r31,hi8(-(a))
    ld r24,Z
    ldd r25,Z+1
    ret

.global    func_2
    .type    func_2, @function
func_2:
    mov r30,r24
    ldi r31,lo8(0)
    lsl r30
    rol r31
    subi r30,lo8(-(a))
    sbci r31,hi8(-(a))
    ld r24,Z
    ldd r25,Z+1
    ret

в полном соответствии со стандартом (цитата из C89, в C99 аналогично)
Обратите внимание - "одно из выражений ... другое ..." а не "первое выражение ... второе ...".
Цитата
3.3.2.1 Array subscripting
Constraints

One of the expressions shall have type ``pointer to object type ,'' the other expression shall have integral type, and the result has type `` type .''

Semantics

A postfix expression followed by an expression in square brackets [] is a subscripted designation of a member of an array object. The definition of the subscript operator [] is that E1[E2] is identical to (*(E1+(E2))) . Because of the conversion rules that apply to the
binary + operator, if E1 is an array object (equivalently, a pointer to the initial member of an array object) and E2 is an integer, E1[E2] designates the E2 -th member of E1 (counting from zero).
Ну а если E1 - интегральный тип а E2 массив (или, что эквивалентно, указатель на его первый элемент), то тогда это будет E1-тый элемент массива E2.

Так что берите на вооружение это и не ограничивайте себя тем, что все массивы должны иметь одинаковую длину. Всё равно в функцию реально передаётся указатель на первый элемент массива - даже когда Вы думаете, что передаёте массив.

А вот ещё из стандарта С++, чтобы окончательно запутать развеять сомнения.
Цитата
When several ”array of” specifications are adjacent, a multidimensional array is created; the constant expressions that specify the bounds of the arrays can be omitted only for the first member of the sequence. [Note: this elision is useful for function parameters of array types, and when the array is external and the definition, which allocates storage, is given elsewhere. ] The first constant-expression can also be omitted when the declarator is followed by an initializer (8.5). In this case the bound is calculated from the number of initial elements (say, N) supplied (8.5.1), and the type of the identifier of D is ”array of N T.”

Except where it has been declared for a class (13.5.5), the subscript operator [] is interpreted in such a way that E1[E2] is identical to *((E1)+(E2)). Because of the conversion rules that apply to +, if E1 is an array and E2 an integer, then E1[E2] refers to the E2-th member of E1. Therefore, despite its asymmetric appearance, subscripting is a commutative operation.


p.s. выделения везде мои


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
Wano
сообщение Jun 13 2009, 23:44
Сообщение #7


Местный
***

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



Код
void func( unsigned size_y, unsigned size_x, char array[size_y][size_x] )
{
    array[2][1] = 'a';
}


в RealView как то не очень прошло,если только size_y не забить статично.

вообще не трогая указатели и typedef пашет и

Код
char array[5][5];

void func(char temp[5][5]){
    temp[1][0]=5;
}

int main (void)
{        
    func(array);
  return 0;
}

Просто массив может быть разной размерности как и способ расчёт их определителя(матрицы), а раз верхний пример не катит, дабы не зацикливаться как на размерности массив так и на размере элементов в функцию кидаю адрес первого элемента :

Код
char array[5][5];

void func(char *temp,char x,char y){
    temp[1*x+1]=5;//[1][1]
}

int main (void)
{        
    func(&array[0][0],5,5);
  return 0;
}

Но никак не получается красивая конструкция типа temp[1][1] . Собственно если отбросить красоту,как помимо (начало+1*x+1) может произойти обращение с помощью скобок к элементам двумерного массива? Конструкция [][] скрывает тот же расчёт, и вроде даже сложнее.Смотрел на:

Код
char array[5][5];
char i=2,j=1;//позиция

void func(char *temp,char x,char y){//x,y размерность    
    temp[i*x+j]=5;
}

int main (void)
{            
    func(&array[0][0],5,5);
    array[i][j]=15;
  return 0;
}
Причина редактирования: Оформление цитат исходников.
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
|- - 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
|- - 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
|- - AHTOXA   Цитата(Wano @ Jun 14 2009, 03:13) ЫЫЫЫЫ ч...   Jun 13 2009, 21:21
|- - 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
- - XVR   Открою великую тайну - как сделать из массива (л...   Jun 10 2009, 09:34
|- - defunct   Цитата(XVR @ Jun 10 2009, 12:34) Открою в...   Jun 14 2009, 03:07
|- - Wano   не рычите люди. С тем, что через void* можно броси...   Jun 14 2009, 09:16
|- - Dog Pawlowa   Цитата(Wano @ Jun 14 2009, 12:16) ...Дайт...   Jun 14 2009, 09:39
|- - Wano   Конкретней : получаем в функции указатель: void f...   Jun 14 2009, 10:04
|- - AHTOXA   Цитата(Wano @ Jun 14 2009, 16:04) Вопрос:...   Jun 14 2009, 10:12
||- - sergeeff   Цитата(AHTOXA @ Jun 14 2009, 14:12) Потом...   Jun 14 2009, 10:31
|- - Сергей Борщ   Цитата(Wano @ Jun 14 2009, 13:04) то не п...   Jun 14 2009, 10:16
|- - Wano   Цитата(Сергей Борщ @ Jun 14 2009, 13:16) ...   Jun 14 2009, 10:34
|- - sergeeff   Цитата(Wano @ Jun 14 2009, 14:34) если за...   Jun 14 2009, 10:51
|- - Wano   Цитата(sergeeff @ Jun 14 2009, 13:51) Жут...   Jun 14 2009, 10:56
|- - sergeeff   Цитата(Wano @ Jun 14 2009, 14:56) как пос...   Jun 14 2009, 11:11
|- - Сергей Борщ   Цитата(Wano @ Jun 14 2009, 13:56) как пос...   Jun 14 2009, 11:33
|- - Wano   Ладно шариться по массиву можно хорошо и так: void...   Jun 14 2009, 12:48
|- - 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
|- - Сергей Борщ   Цитата(Wano @ Jun 14 2009, 15:48) мне хот...   Jun 14 2009, 16:33
- - sergeeff   Да, блин! Все рассказали, объяснили, примеры п...   Jun 14 2009, 00:16
- - sergeeff   Не хочет народ читать книги отцов-основателей. Дл...   Jun 14 2009, 10:08


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

 


RSS Текстовая версия Сейчас: 7th August 2025 - 07:40
Рейтинг@Mail.ru


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