как объяснить такое поведение PROGMEM
- Войдите на сайт для отправки комментариев
Ср, 10/07/2019 - 20:17
Добрый день старожилы и гуру.
Заметил что ни смотря на наличие прогмем атрибута, компилятор не всегда помещает строки во флэш. Не могли бы вы объяснить чем рукаводствуется компилятор/почему так происходит ?
первый пример. если объявляем без инициализации то list[3] не сохраняется во флэш
const PROGMEM char one[] = HELLO; const PROGMEM char two[] = WORD; const PROGMEM char three[] = WORD; //const PROGMEM char *const list[] = {one, two, three}; const PROGMEM char *const list[3];
второй пример. если элементы list массивы как выше то сохраняет во флэш. если так, то нет.
const PROGMEM char *const one = HELLO; const PROGMEM char *const two = WORD; const PROGMEM char *const list[] = {one, two};
Все, что находится в ПРОГМЕМ - по определению константа. Все константы должны быть проинициализированы в момеент декларации, поэтому в первом примере в ПРГМЕМ пишется пустой массив.
Во втором примере вы создаете в ПРОГМЕМ не строки, а пустые указатели в никуда.
Ну и в третьих забавные строки у вас.
Ну а еще - тут нет никакого особенного "поведения ПРОГМЕМ". Все перечисленные вопросы не имеют ровно никакого отношения к ПРОГМЕМ вообще - просто вы элементарно не знаете Си
я не знаю Си.
"поэтому в первом примере в ПРГМЕМ пишется пустой массив.", пустой да. но вот в прогмем то он и не пишется. я про это спрашивал. он отжирает память из SRAM
"Во втором примере вы создаете в ПРОГМЕМ не строки, а пустые указатели в никуда." - почему в никуда? и даже если никуда то опять же не в прогмем они пишуться а в SRAM. я про это спрашивал
а чем строки забавные ? #define HELLO "Hello" вы же не подумали что HELLO это и есть строка
я не знаю Си.
Так, может, уж выучить?
Всё, что нужно знать про массивы в прогмем - http://arduino.ru/forum/programmirovanie/ocherednoi-raz-progmem#comment-336371
Я на основе этого поста и писал свой вопрос. Что там написано все понятно. Но там нет ответа на мои вопросы.
Все твои дискуссии одинаковы. тебе говорят "ты не понял", ты начинаешь доказывать, что "понял, только не работает". Ну, раз у людей работает, а у тебя - нет, значит не понял!
Так, давай внятно рассказывай что у теб сохраняется, а что нет (не "как выше", а внятно). И заодно, обязательно скажи, с чего ты взял, что оно сохраняется или нет - как ты это проверял?
Так и у меня работает. Я же описал как работает и как нет. С - как работает- все понятно.
Проверял с тем вариантом , где точно сохраняется.
Рассказываю внятно
Вариант 1.а рабочий - как поместить три строки во флэш и все это в *list [] , мы знаем и занимает это sram памяти с учетом программы 400байт. Повторяю строки во флэш.
Вариант 1.b не рабочий - заменяем строчку с массовом указателей на такую const PROGMEM char *const list[3]; остальное не трогаем, и теперь оперативки на 6 байт меньше (ровно наши три пустых указателя). Почему три пустых указателя не помещаются во флэш?
Вариант 2.а рабочий - опять же наши строки во флэш
Вариант 2.b не рабочий - меняем только первую строчку.
Было const PROGMEM char one[] = "HELLO";
Стало const PROGMEM char *const one = "HELLO";
Оперативки стало на 6 байт меньше, ровно наша строчка. Почему указатель на литерал не сохраняется во флэш точно также как массив символов ?
Помниться даже в 90ые на ассемблере в zx spectrum +- пару сотен байт никому не важно было....а тут вам 6 байт не хватило - вы нормальный?
да нет, дело то не байтах. просто у ТС такие хобби - сначала сделать неправильно, а потом у всех допытываться, "Почему не работает?"
У вас предупреждения в компиляторе включены?
Дело в том, что помещение пустого массива в ПРОГМЕМ строчкой
const PROGMEM char *const list[3];
- абсолютно бессмысленная операция. Настолько бессмысленная. что это очевидно даже для тупого железного компилятора, так что я не исключаю, что компилятор выдает вам предупреждение о недопустимости создания неинициализированного массива в ПРОГМЕМе и исправляет вашу ошибку, помещая массив в оперативку.
Вариант 1.b не рабочий - заменяем строчку с массовом указателей на такую const PROGMEM char *const list[3]; остальное не трогаем, и теперь оперативки на 6 байт меньше (ровно наши три пустых указателя). Почему три пустых указателя не помещаются во флэш?
Попробовал скомпилировать ваши варианты 1а и 1в -
1а = флеш 1452 байта. оперативки 184 байта
1в = флеш 1430 байт, оперативка 184
Никакие шесть байтов от RAM не отъедаются, а то что первый вариант на 22 байта больше во флеше - так это вполне ожидаемо, так как во втором варианте строчки в программе не используются и компилятор их выкинул
Иде 1.8.3, плата Ардуино Уно
К тому же если не пользоваться pgm_read_??? при попытке вывода массивов из PROGMEM компилятор всегда будет резервировать место в оперативке. Будет казаться по размеру памяти программы что всё плохо.
Ну правильно если их не использовать компилятор вообще их оптимизируют до уничтожения. Поэтому у вас оперативка одинаковая. Могу скинуть позже пример с разной оперативкой.
"потому что пустой поэтому помещаем в оперативк" - ну он сейчас так и делает. Я это еще в первом посте сказал. Но я например ожидаю размещение во флэш тк атрибут прогмем у нас. Или ошибку что надо инициализировать. А не так что компилятор делает по своему и нас не слушает.
А Про второй вопрос где не все так очевидно, есть соображения?
Даже компилятор понял, что нет смысла Вас слушать и объяснять как не стоит писать, а надо делать как его научили.
Вариант 1.а ...
Вариант 1.b ...
Вариант 2.а ...
Вариант 2.b ...
Ну, и где эти обозначения в примерах кодов? Как мне понять, где какой вариант? Давай так, я обещаю честно всё посмотреть и прокомментировать что и как, но напиши ты, наконец, понятный вопрос, где не нужно было бы догадываться что ты имеешь в виду. Сделаешь?
И ещё. Выложи код, которым ты проверяешь поместила она во флешь или нет. А то доверия к твоему умению что-то делать, извини, невелико.
Сдаётся мне, что тут сохраняется в прогмеме указатель на строку в RAM, а не сама строка.
"Число правильных вариантов - ограничено, неправильных - бесконечно" (с) мой :)
Ну, и чего ж тебе понятно по той ссылке, если ты всё сделал не так?
А твоём первом примере в прогмем попадает массива символов. А во втором, масив остётся в рам, а в прогмем попадает значение указателя на него.
ну так а я что спрашивал в первом посте. хоть там и не массив а указатель (ты опечатался наверно) но это я и спрашиваю. почему если массив прогмем то он во флэш а если указатель прогмем то он не хочет во флэш?
и почему нулевой в раме может быть а в прогмем нет ?
и почему нулевой в раме может быть а в прогмем нет ?
потому что смысла нет, в ОЗУ выделяется пустое место для работы.
почему если массив прогмем то он во флэш а если указатель прогмем то он не хочет во флэш?
Прежде всего - все данные, в сущности, располагаются в Progmem Space. Изначально. Но после, так как компилятор не был проинструктирован не вставлять в прошивку операции копирования данных в RAM, они туда дублируются. Всё.
Все фантазиии насчёт хочет / не хочет - это недопонимание происходящих процессов.
так мы же проинструктировали компилятор что это не нужно копировать в рам а он редиска всеравно взял и скопировал
const
PROGMEM
char
*
const
one =
"NUMBER1"
;
Проинструктирован оставить без копирования в PROGMEM char* - он и оставлен. Насчёт остального распоряжений не поступало.
а как про остальное ему намекнуть ?
а как про остальное ему намекнуть ?
http://arduino.ru/forum/programmirovanie/progmem-tricks#comment-439006
потому что смысла нет,
какое дело железке до смысла. компилятору данна четкая команда что мы хотим разместить пустой указатель во флэш. он должен либо сделать то что от него ждут либо рапортовать об ошибке если не может (хотя он это может сделать если немного по другому)
А твоём первом примере в прогмем попадает массива символов. А во втором, массив остаётся в рам, а в прогмем попадает значение указателя на него.
Т.е. указатель как раз хочет и попадает. Не попадает то, на что он указывает.
Теперь ответ на вопрос "почему так". Ответ очень простой - потому, что ты так написал.
В прогмем можно пихать что угодно. Что программист хочет, то и пихает. Кто-то пихает туда сам массив, кто-то указатель на него, а кто-то и то и другое. Именно об этом был пост, который я тебе "проссылил" и который ты "понял". Так вот ты написал "запихать туда указатель, а то, на что он указывает - оставить в RAM". Компилятор ответил "Есть, сэр!" и сделал именно это.
какое дело железке до смысла.
Слышал такое слово "оптимизация"? Вот железка и удаляет из программы всё, что никак не используется и не может использоваться. Она (железка), похоже, поразумнее некоторых программистов будет.
А твоём первом примере в прогмем попадает массива символов. А во втором, массив остаётся в рам, а в прогмем попадает значение указателя на него.
сори проглядел написанное. как заставить компилятор саму строку засунуть в PGM (чтоб по итогу получить и поинтер и литерал во флэш)? без объявления массива
судя по всему никак , правильно я понимаю?
Вот железка и удаляет из программы
ну она не удаляет а рзмещает в рам. плюс переменная то используется в том примере. и компилятору вроде должно быть всеравно откуда использовать перемнную. а мы ему чтоб он долго не думал указываем пускай оно полежит во флэш. причем если явно объявить её как NULL то он разместит во флеш. а если не инициализированна (при этом она тоже NULL) то в рам. честно но в данном конкретном примере явно железка тугодумит
ну она не удаляет а рзмещает в рам.
ни хрена не размещает - именно удаляет.
сори проглядел написанное. как заставить компилятор саму строку засунуть в PGM (чтоб по итогу получить и поинтер и литерал во флэш)? без объявления массива
судя по всему никак , правильно я понимаю?
Почему, никак - размещай на здоровье, если умеешь.
Если хочешь, чтобы я тебе учил этому, для начала объясни мне нахрена тебе это нужно, чем тебе [] не угодили? А то будет как всегда - тратишь часы. а выясняется. что надо было не это, просто человек вопросы задавать не умеет.
"Число правильных вариантов - ограничено, неправильных - бесконечно" (с) мой :)
Ой ли!
Я это слышал еще в исполнении А. Райкина. Значит, скорее всего, (с) М. Жванецкий.
именно удаляет.
а что тогда размещается в оперативки ровно на длину строки ?
объясни мне нахрена тебе это нужно, чем тебе [] не угодили?
да всем угодил . просто знать как еще можно ?
именно удаляет.
а что тогда размещается в оперативки ровно на длину строки ?
Слушай. с тобой невозможно разговаривать, ты скачешь с пятого на десятое никого не предупреждая. Я говорил о
const
PROGMEM
char
*
const
list[3];
Какой тут нахер строки????
------------
В общем, так, теряется много времени на беспорядочные тексты. Давай наведеём порядок.
Сейчас я хочу знать насколько ты понимаешь самые основы. Потому жду ответа на вопрос деда. Всё остальное я игнорирую (в том числе и вопрос "какой тут ..." выше - не отвечай!).
Хочешь помощи - делай что говорят.
я не знаю Си.
Проштудируй К&R. Вопросы отпадут сами.
да согласен давай по одному вопросу. ато путаемся.
const
PROGMEM
char
*
const
list[10];
у меня было 10 чтоб меньше мосх ((с)Дед) напрягать. оперативки на 20 байт меньше. других же изменений в программе не было. значит это не инопланетные наводки. и не произвол компилятора. это ровно наши 10 указателей в оперативке. еслиб оно просто удалилось как ты говоришь то оперативка бы не изменилась. ?
Ты КАК ВСЕГДА не приводишь полный код, который я могу скомпилировать и посмотреть. Повторится ещё раз, просто пошлю тебя нафиг - задолбало тебе одно и то же писать.
Вот смотри, твой пример (и кстати, смотри как надо вопросы задавать, чтобы тебя понимали)
Вот такой код (прямо сейчас скомпилировал)
у меня занимает 444/9
Вставляем твой массив, компилируем
по-прежнему 444/9 - значит, массив выброшен.
Вставляем какое-нибудь использование твоего массива
теперь получилось 460/9. Разница в 16 байтов. Для массив этого мало. Вывод - он по-прежнему выбрасывается. А эти 16 байтов - вывод 10 раз нуля в регистр TCNT1
Надеюсь, ты понял как надо задавать вопросы? Вот ты пишешь про 20 байтов. А у меня получается 16. Чтобы понять что происходит, я хочу видеть твои 20. Так покажи же их мне! Я всю тему тебя прошу - вставляй ПОЛНЫЕ коды.
Не будешь этого делать, разбирайся сам.
Подолью маслица.
1. w/o USE_PROGMEM
К тому же компилятор выдаёт сообщение: warning: uninitialized variable 'list' put into program memory area [-Wuninitialized] -> const PROGMEM char *const list[10];
Ежели оптимизацию включаем, то соопчения нет - бесполезный функционал выкидывается до линковки.
К тому же компилятор выдаёт сообщение: warning: uninitialized variable 'list' put into program memory area [-Wuninitialized] -> const PROGMEM char *const list[10];
Ежели оптимизацию включаем, то соопчения нет - бесполезный функционал выкидывается до линковки.
О! про то, что должно быть предупреждение - я писал ТС в сообщении #9. А оно, оказывается, при оптимизации не выдается...
У меня и с оптимизацией (Os) выдаётся, но другое "warning: uninitialized const 'list' [-fpermissive]"
Ворота, пример как ты и просил привёл выше. Вот дублирую еще раз. Запускай на здоровье и смотри как проподает оперативка на 20 байт.
Получается ворота ты брешишь :) размещается то в рам массив указателей и пример был в15 посте. Ох уж эти профессионалы :)
Это ты меня на слабо что ли берёшь? Смешной ты.
Ты, похоже, так и не понял, что вчера произошло. Я задолбался писать тебе одно и тоже, в итоге, вчера, после того как в ответ на прямую (трёхкратную) просьбу писать без ссылок, ты дал мне ссылку, я понял, что имею дело либо с троллем, котороый издевается надо мной, либо с идиотом, который не понимает простых фраз. Тогда ты был "послан на". Так что никакие "брешишь" не вернут меня к попыткам что либо объяснить тебе. Троллям и идиотам объяснять бесполезно.
Кстати, я заметил, что у тебя практически каждая тема заканчивается обвинениями, что профессиналы - козлы, один ты весь в белом. Вот и оставайся в белом, не лезь к нам, а то испачкаешься.
То другая тема. Если ты обиделся на прямой линк - можешь не отвечать в той теме, твое дело. Тут я тебе сразу ответил 15 пост. Если ты считаешь, после того как я сделал все что ты простил, сдал все твои экзамены, что можно просто покинуть тему.... То ты показал что ты за человек.
Я считаю, что ты либо тролль, либо идиот. Что ты ещё раз подтвердил не поняв (сделав вид, что не понял) написанного в посте #45. А я предпочитаю не общаться ни с троллями, ни с идиотами.
Да, это так.
Конечно , брехать не мешки таскать
1. На очевидный пример N3 где переменная в рам утверждает что она не в рам
2. Строку без массива тоже не запихнул во флэш, а говорил у меня нет проблем со строками