roboforum.ru

Технический форум по робототехнике.

Массив константных указателей на константный массив констант

Как собрать и запрограммировать робота на Arduino(Freeduino, Roboduino, Seeduino ...). Используем Wiring и Processing.

Массив константных указателей на константный массив констант

Сообщение HarryStar » 17 фев 2017, 13:54

Есть проблемка.
Нужно разместить двухмерный массив строк во флеше.
С одной строкой не проблема:
Код: Выделить всёРазвернуть
const char s1[] PROGMEM = "123";

С массивов строк тоже проблем нет:
Код: Выделить всёРазвернуть
const char s1[] PROGMEM = "123";
const char s2[] PROGMEM = "456";
const char s3[] PROGMEM = "789";

const char* const ss[] PROGMEM = {s1, s2, s3};

А вот мне надо массив этих массивов. В идеале тоже в PROGMEM, но необязательно, т.к. он уже маленький
Компилятор пропускает такие варианты:
Код: Выделить всёРазвернуть
const char** const table_in_flash[] PROGMEM = {ss, ss1, ss2};
const char* const *table_in_ram[] = { ss, ss1, ss2};


Вариант с PROGMEM у меня не получилось заставить работать вообще.
Вариант с оперативкой частично работоспособен. А именно:

Можно получить доступ к конечным строкам побайтно pgm_read_byte_near((char*)pgm_read_word(&(table_in_ram[набор строк][строка])) + символ);
Можно узнать размер любой строки strlen_P((char*)pgm_read_word(&(table_in_ram[набор строк][строка])))
Можно получить количество наборов sizeof(table_in_ram)/sizeof(char*)

Но! Никак не получается получить количество строк в наборе через table_in_ram.
Комбинация sizeof(table_in_ram[0]) выдает все время 2 вне зависимости от количества строк в наборе.
Пробовал разные варианты типа sizeof((char**)pgm_read_word(*(table_in_ram[0]))))
Никак! При этом sizeof(ss) работает и выдает корректный результат, который мне надо получить через массив table_in_ram.

Честно говоря не надеюсь особо на ответ, т.к. задача нестандартная. Копаю... Если кому-то интересно, отпишу если нарою.
Аватара пользователя
HarryStar
 
Сообщения: 995
Зарегистрирован: 15 ноя 2010, 13:56
Откуда: Нижний Новгород
прог. языки: С, С++, РНР

Re: Массив константных указателей на константный массив конс

Сообщение Dmitry__ » 17 фев 2017, 14:00

Зачем так мучить бедный авр** ?
Делай программную обработку своего многомерного массива...
Аватара пользователя
Dmitry__
 
Сообщения: 8033
Зарегистрирован: 13 янв 2011, 15:25
Откуда: Санкт-Петербург

Re: Массив константных указателей на константный массив конс

Сообщение HarryStar » 17 фев 2017, 14:52

Все и делается для программной обработки массива.
Мне просто нужно несколько наборов строк, доступ к ним мне нужен из одной общей точки типа table_in_ram в примере. Строки эти часто изменяются, количество их в наборе и количество самих наборов тоже меняется. Мне удобно поправить массив, добавить новый и все. И не дописывать #define с количеством элементов в массиве. Хочется получить размерность массивов штатными средствами.
Аватара пользователя
HarryStar
 
Сообщения: 995
Зарегистрирован: 15 ноя 2010, 13:56
Откуда: Нижний Новгород
прог. языки: С, С++, РНР

Re: Массив константных указателей на константный массив конс

Сообщение Dmitry__ » 17 фев 2017, 15:19

Ссылка ссылки на ссылку трудночитаемая конструкция как и название темы :) "Массив константных указателей на константный массив констант". Во что это компилится лучше вообще не думать. Такое можно делать на gcc самых свежих версий для 686 компов. Но не для дистрофиков типа авр.
Надо выделить память, сделать указатель на эту память. И только там уже реализовывать все самые эротические мечты с метками конца строк, счетчиком строк и.т.д. Во-первых такой код будет понятен самому себе, во-вторых не будет хождения по граблям при интерпретации знаний о sizeof, calloc, malloc, free. Это все ацкие вещи, в embedded они лишние...
Аватара пользователя
Dmitry__
 
Сообщения: 8033
Зарегистрирован: 13 янв 2011, 15:25
Откуда: Санкт-Петербург

Re: Массив константных указателей на константный массив конс

Сообщение HarryStar » 17 фев 2017, 15:40

Вот спрашиваешь конкретный вопрос, а вместо ответа получаешь "а зачем ты этот вопрос задал? Может лучше другой?".

Ключевое слово в коде PROGMEM как бы должно намекать что сделано все это для экономии памяти и реальных строк там на 20кб при оперативке меньше 2кб. Поэтому разместить в память, выделить и т.д. не подходит в принципе. Подходит ТОЛЬКО тот вариант что я написал.

И он ни во что не компилится, т.к. это просто массив данных во флеш памяти. И массив указателей на эту флеш память. Работа с указателями для си компилится отлично в нормальный код. И на arduino.cc полно примеров работы с PROGMEM, но к сожалению нет примера с двойными указателями.

Проблема тут исключительно с макросами pgm_read_, просто думал кто-то их знает хорошо.
Аватара пользователя
HarryStar
 
Сообщения: 995
Зарегистрирован: 15 ноя 2010, 13:56
Откуда: Нижний Новгород
прог. языки: С, С++, РНР

Re: Массив константных указателей на константный массив конс

Сообщение Dmitry__ » 17 фев 2017, 16:12

Ну ладно, не ругайся :)
Твой вопрос трудно понятен как и двойные ссылки. Еще менее понятны только тройные ссылки. Если массив состоит только из констант, то нет смысла это все так описывать. Все можно сделать дефайнами. Если проблема с вычисляемыми указателями на строки констант, то их надо просто сгенерить дефайнами.
Скорее всего я вообще не понял вопроса, надо ждать еще одно мнение. :)

Добавлено спустя 10 минут 20 секунд:
Re: Массив константных указателей на константный массив констант
Во, скажи что ты пытаешься реализовать. А я поумничаю зачем так не надо делать :crazy:
Уж не записанные фразы выдавать в rs232? И проблема с индексацией этих фраз?

Добавлено спустя 9 минут 56 секунд:
Re: Массив константных указателей на константный массив констант
Не?
http://microsin.net/programming/avr/avrstudio-gcc-progmem.html
[Сохранение строк в памяти программ и получение их оттуда]

Предположим, у нас есть массив строк:

char *string_table[] =
{
"String 1",
"String 2",
"String 3",
"String 4",
"String 5"
};
Теперь добавляем макро PROGMEM и ключевое слово const:

const char *string_table[] PROGMEM =
{
"String 1",
"String 2",
"String 3",
"String 4",
"String 5"
};
Верно? Нет! К сожалению, атрибуты GCC затрагивают только объявление, к которому они присоединены. В этом случае мы действительно поместили переменную string_table, т. е. сам массив, в память программ, но не сами строки. Строки так и остались в памяти данных (RAM), что наверное не совсем то, то Вы хотели. Чтобы поместить строки во flash, нужно явно объявить каждую строку:

const char string_1[] PROGMEM = "String 1";
const char string_2[] PROGMEM = "String 2";
const char string_3[] PROGMEM = "String 3";
const char string_4[] PROGMEM = "String 4";
const char string_5[] PROGMEM = "String 5";
И потом использовать новые символы в массиве:

PGM_P string_table[] PROGMEM =
{
string_1,
string_2,
string_3,
string_4,
string_5
};

Аватара пользователя
Dmitry__
 
Сообщения: 8033
Зарегистрирован: 13 янв 2011, 15:25
Откуда: Санкт-Петербург

Re: Массив константных указателей на константный массив конс

Сообщение loox » 18 фев 2017, 02:04

на самом деле не понял вопроса, но..
1. Многомерный массив, в соответствии с синтаксисом языка есть массив массивов.
Определение многомерного массива в общем случае : type имя_массива [A1][A2]....[An];
где type - допустимый тип
имя_массива - идентификатор
n - размерность массива масивов
A1 - размерность первого массива.
Пример: int adafaha [4][5][2];
2. поскольку вы используете инструкцию для компилятора PROGMEM, т.е располагаете некоторые данные, фактически константы, в памяти программ, то Ваша конструкция с многомерными массивами и указателями теряет всяческий смысл. Вот почему:
а) это константы
б) размерность каждого из массивов Вам известна
в) количество массивов Вам точно известно.
Располагайте все данные как одномерный: первый элемент, первого массива будет: имя_массива[0] последний элемент первого массива будет: имя_массива[0+n] где n - длина первого массива, первый элемент второго массива будет: имя_массива[0+n+1] и так далее. Это понятней и легко реализуемо.
Спасибо loox
loox
 
Сообщения: 326
Зарегистрирован: 26 мар 2008, 12:45

Re: Массив константных указателей на константный массив конс

Сообщение HarryStar » 18 фев 2017, 11:06

loox писал(а):на самом деле не понял вопроса, но..

.. поспешил дать бесполезный ответ на какой-то другой вопрос. Типа спасибо, но что такое многомерные массивы и даже массивы указателей на массивы указателей на указатели я узнал более 25 лет назад :)

Dmitry__ писал(а):Не?

В начале вопроса я написал что с одиночными строками и в массивом строк проблем нет. Это как раз то, что описывается в этом примере. Его и мусолят во всем интернете, затрудняя поиск по моей проблеме. Мне нужен следующий уровень. Мне нужен массив того, что указано в примере. И из-за того, что данные оттуда напрямую не видны (из за PROGMEM), приходится пользоваться макросами pgm_read и в этом вся проблема.

Задачу я описал, опишу более абстрактно:
Есть примерно 20 кб текста в виде наборов строк. Наборов сегодня 3, завтра 5, послезавтра 2. В каждом наборе 20-100 строк, везде разное.
Хотелось бы менять только объявление массива без дополнительных дефайнов, где фигурировало бы количество наборов, и количества строк в каждом наборе. И получать доступ к данным через 1 массив.

Потом идет поиск соответствия строки внутри этого массива. Т.е. цикл по количеству наборов, внутри цикл по количеству строк внутри набора (оно разное для всех наборов).
Раньше все это работало с SD карты, там это было разнесено по разным файлам, но сейчас концепция поменялась и нужно эту таблицу запихать в Ардуину.

Работает ВСЕ, кроме того как узнать количество строк в наборе. Я пока делаю обходным путем, после последней строки в наборе вставляю NULL и проверяю следующую ссылку перед использованием. Нормально, но для оптимизации мне лучше было бы знать заранее количество строк.
Аватара пользователя
HarryStar
 
Сообщения: 995
Зарегистрирован: 15 ноя 2010, 13:56
Откуда: Нижний Новгород
прог. языки: С, С++, РНР

Re: Массив константных указателей на константный массив конс

Сообщение loox » 18 фев 2017, 11:26

не может быть сегодня одно а завтра другое ...вы загружаете свои многомерные массивы в память программ - PROGMEM
Они не могут быть изменены!!!! - это константы. Их изменить можно только путем перепрошивки микропроцессора.
loox.
loox
 
Сообщения: 326
Зарегистрирован: 26 мар 2008, 12:45

Re: Массив константных указателей на константный массив конс

Сообщение HarryStar » 18 фев 2017, 12:08

loox писал(а):не может быть сегодня одно а завтра другое

Может. если каждый день перепрошивать. Не надо додумывать за других задачу. Вам моя задача в полном объеме не нужна и неинтересна. Я вырезал и логически и программно кусок, в котором у меня возникли сложности.
Аватара пользователя
HarryStar
 
Сообщения: 995
Зарегистрирован: 15 ноя 2010, 13:56
Откуда: Нижний Новгород
прог. языки: С, С++, РНР

Re: Массив константных указателей на константный массив конс

Сообщение Dmitry__ » 18 фев 2017, 13:19

А чего такой нервный? Тебе все правильно говорят. Ты уверен что все понимаешь? Даже после 25 лет? :wink: Например с sizeof???
HarryStar писал(а):Комбинация sizeof(table_in_ram[0]) выдает все время 2 вне зависимости от количества строк в наборе.


Все правильно, размер ячейки, как ты и просил, или ты думал о другом? Нервный ты наш. А что она должна еще там выдавать? :shock:

HarryStar писал(а):Но! Никак не получается получить количество строк в наборе через table_in_ram.

Может из-за того, что компилятор не знает текущего размера резинового массива? Или ты думаешь что sizeof - высокоинтеллектуальная функция по подсчету размера всего и вся? Может это просто макрос, который выдает размер в байтах известного заранее типа? :wink:
Еще раз перечитай вдумчиво:
во-вторых не будет хождения по граблям при интерпретации знаний о sizeof, calloc, malloc, free. Это все ацкие вещи, в embedded они лишние...


HarryStar писал(а):И из-за того, что данные оттуда напрямую не видны (из за PROGMEM), приходится пользоваться макросами pgm_read и в этом вся проблема.

Ого, смело :shock: Может стоит открыть pdf на контроллер, вдумчиво его покурить и написать свою функцию чтения флеш?

Тебе стоит еще 25 лет поучиться. Я не стесняюсь учиться всю жизнь...

Добавлено спустя 6 минут 28 секунд:
Re: Массив константных указателей на константный массив констант
Кури:
http://www.cyberforum.ru/cpp-beginners/thread435041.html
Если массив динамический sizeof всегда возвращает размер указателя в 4 байта...
char * DinArr = new char[N];
sizeof(DinArr) - вернёт четыре байта...
Аватара пользователя
Dmitry__
 
Сообщения: 8033
Зарегистрирован: 13 янв 2011, 15:25
Откуда: Санкт-Петербург

Re: Массив константных указателей на константный массив конс

Сообщение loox » 18 фев 2017, 13:34

Ну как хотите, спорить не буду.
Но читать и разбираться в чужом коде, с сомнительным качеством - занятие неинтересное..
За сим откланиваюсь.loox
loox
 
Сообщения: 326
Зарегистрирован: 26 мар 2008, 12:45

Re: Массив константных указателей на константный массив конс

Сообщение HarryStar » 18 фев 2017, 15:28

Dmitry__ писал(а):А чего такой нервный? ... Тебе стоит еще 25 лет поучиться. Я не стесняюсь учиться всю

Нисколько не стесняюсь учится, тем более что программирования для меня не профессия а хобби. Знал бы все досконально, не спрашивал бы. Про 25 лет я сказал совсем не в ключе что я мега-опытный, возможно не совсем корректно прозвучало. Просто человек не вникнув в вопрос дал выдержку из википедии про многомерные массивы, не связанную по теме даже близко.

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

Я не нервный, просто не люблю когда в качестве ответа кидают первую ссылку из инета по одному случайно выбранному в вопросе слову типа "многомерный" как сделал уважаемый тов. loox.
Аватара пользователя
HarryStar
 
Сообщения: 995
Зарегистрирован: 15 ноя 2010, 13:56
Откуда: Нижний Новгород
прог. языки: С, С++, РНР

Re: Массив константных указателей на константный массив конс

Сообщение Dmitry__ » 18 фев 2017, 16:17

Нет, ты отвечал именно нервно. Он тебе все правильно ответил, ибо:
loox писал(а):не может быть сегодня одно а завтра другое


И твой ответ:
HarryStar писал(а):Может. если каждый день перепрошивать. Не надо додумывать за других задачу.


И твой ответ в корне неправильный. Т.к. константы остались константами, "каждый день перепрошивать" - не есть алгоритм обработки размера массива. Поэтому, что sizeof, что дефайны делают абсолютно одно и тоже. И тебе это пытались донести. Но не зная что sizeof - тупой макрос компилятора, можно начать говорить о 25 годах умения, и что все отвечают на не тот вопрос.
Кста, со мной у тебя тоже не очень-то и получалось "Вот с тобой диалог более осмысленный и ты натолкнул", т.к. ты меня послал туда же куда и его :)
HarryStar писал(а):Вот спрашиваешь конкретный вопрос, а вместо ответа получаешь "а зачем ты этот вопрос задал? Может лучше другой?".


И только мое спокойствие довело до: :beer: :friends:
Аватара пользователя
Dmitry__
 
Сообщения: 8033
Зарегистрирован: 13 янв 2011, 15:25
Откуда: Санкт-Петербург


Вернуться в Arduino и другие Xduino

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 5