Сергей Борщ 134 9 января, 2014 Опубликовано 9 января, 2014 · Жалоба А каким образом это делается? Буквально в двух словах, если можно.На примере GCC: константы складываются в секции .rodata и .rodata.* Если вы в скрипте линкера разместите эти секции в flash (выходная секция .text), то они там и будут жить. А если вы поместите их в выходную секцию .data, то они будут размещены в ОЗУ и проинициализированы из флеша. Примерно так: .data : { . = ALIGN(4); _sdata = .; /* start of .data label */ *(.ramfunc) *(.ramfunc.*) *(.data) *(.data.*) *(.rodata) /* read-only data (constants) */ *(.rodata.*) . = ALIGN(4); _edata = .; /* end of .data label */ } > RAM AT > TEXT _sidata = LOADADDR(.data); /* start of initialized data label */ На ARMах const в определении переменной заставляет компилятор (и линкер) размещать её во флэше.Компилятор - помещать ее в секцию данных "только для чтения". А линкер - размещать ее там, куда укажут в управляющем скрипте. Для прошиваемых намертво в небольшие процессоры программ эта секция обычно размещается во флеш. А вот если процессор побольше и программа загружается в огромное динамическое ОЗУ из какой-нибудь последовательной флешки - то и секцию констант программист скорее всего разместит в ОЗУ. static const Строка просто const из flash переписывается в ОЗУ, и уже из ОЗУ используется в функции. Лично сталкивался. Это какая-то чудовищная недоработка вашего компилятора. Допустим вы в файле myfile1.c размещаете глобальную переменную: char const Success_string[] = "Слава мне, победителю драконов"; Если вы объявите ее с квалификатором static, то ее область видимости будет ограничена только этим файлом и вы не сможете в файле myfile2.c написать extern char const Success_string[]; void test() { puts(Success_string); } А без static - сможете. И нет никаких объективных причин для компилятора размещать константу в одном случае в ОЗУ а в другом - во флеш. .... Хотя... Я, кажется, понял в чем дело - вы имели дело с локальными переменными функции. В этом случае да, без static компилятор обязан создать переменную в точке объявления и уничтожить ее в конце области видимости. И сделать он это может только в ОЗУ. А с добавлением static к объявлению локальной переменной она перестает быть автоматической и может быть размещена во флеше, что вы и наблюдали. То есть никакой мистики тут нет и все происходит строго в рамках стандарта. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 9 января, 2014 Опубликовано 9 января, 2014 · Жалоба Я, кажется, понял в чем дело - вы имели дело с локальными переменными функции. Да, с локальными строками. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 134 9 января, 2014 Опубликовано 9 января, 2014 · Жалоба Да, с локальными строками.О. А тут все о глобальных переменных спорили ;) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Tarbal 4 9 января, 2014 Опубликовано 9 января, 2014 (изменено) · Жалоба Ну вот где вы такое видели применительно к языку C в реальном мире? На 51 уж 15 лет не писал, а на AVR и PIC реально размещал и утрамбовывал память. К сожалению давно не программирую на этих процессорах. У кого есть IAR AVR? Давайте простую программу напишем и создадим листинг ассемблерный. Тогда все станет ясно. Заодно map файл посмотрим. Оптимизацию надо отключить char str1[] = "12345"; const char str2[] = "54321"; char* ptr; int main () { char ch; ptr = str2; ch = *ptr; ptr = str1; *ptr = ch; ptr++; ch = *ptr; ch=ch; return 0; } Изменено 9 января, 2014 пользователем Tarbal Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrewlekar 0 10 января, 2014 Опубликовано 10 января, 2014 · Жалоба Что вы этим гениальным кодом хотите проверить? В ch сначала попадёт '5', затем в str1[0] запишется '5', затем в ch запишется '2', а строка ch=ch ничего не делает - она заоптимизируется почти всегда. Ах да, str1 и str2 будет размещено в ОЗУ. Если вы хотели str2 размещать во флэш, то надо было указать квалификатор __flash. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Edit2007 3 10 января, 2014 Опубликовано 10 января, 2014 · Жалоба то надо было указать квалификатор __flash. Об этом и речь квалификатор __flash - это расширение для данной архитектуры. Для стандарта языка квалификатор const - запрет на изменение переменной, не важно локальная она или глобальная. Размещенеие переменной в памяти - дело линкера. На тех же 51-х архитектурах обычный указатель содержит 3 байта - 2 адрес объекта (переменной) и один байт тип памяти, где этот объект распложен. А далее библиотека раскручивает цепочку и выбирает способ считывания данных. Но возможно и прямое указание типа памяти квалификаторами idata, xdata, code. (применительно к KEIL, у ИАР думаю похожая ситуация в отношении МCS-51). const только запрещает изменение перемнной не более того. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrew_b 16 10 января, 2014 Опубликовано 10 января, 2014 · Жалоба const только запрещает изменение перемнной не более того.Только в случае с указателем есть одна тонкость. const void *x; -- это указатель на константу. Вы не можете изменить то, на что он указывает, но можете изменить его самого: x = &y; void *const x; -- константный указатель. Вы не можете изменить этот указатель, но можете изменить то, на что он указывает: *x = y; const void *const x; -- константный указатель на константу. Вы не можете изменить ничего. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 10 января, 2014 Опубликовано 10 января, 2014 · Жалоба Удостоверился в Кейл для глобальных переменных: - const (и static const, естественно) размещаются и используются из flash, - инициализированные переменные без квалификаторов (и volatile, естественно) при старте из flash переносятся в RAM и уже там используются. Конкретно задавать нестандартные квалификаторы не вижу необходимости. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 134 10 января, 2014 Опубликовано 10 января, 2014 · Жалоба Удостоверился в Кейл для глобальных переменных:Для процессора с линейным адресным пространством (ARM, Cortex). Для x51 все запутаннее - там есть и медленные generic указатели (с отметкой об адресном пространстве в старшем байте и с генерацией кодов доступа ко всем пространствам при обращении по такому указателю) и указатели на конретное адресное пространство (с квалификаторами data, idata, xdata и т.д). Тут подробнее. Насколько помню, по умолчанию (без спецификатора адресного пространства) константы располагаются в памяти data, т.е. в непосредственно адресуемом ОЗУ. С C166 не работал, не знаю, но судя по сегментированному адресному пространству тоже должны быть хитрости. Для других процессоров Keil вроде как компиляторов не делает. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 10 января, 2014 Опубликовано 10 января, 2014 (изменено) · Жалоба В C можно структуру передавать в функцию, именно, по значению, а не по ссылке. Т.е., имя структуры не есть ее адрес. В отличие от массива. Ну и как это связано с явным преобразованием идентификатора структуры? Разве при этом недостаточно информации о том, что "заказчик" желает взять именно её адрес? Более интересна ситуация, которую я нашёл у себя в исходниках, применения явного преобразования адреса к локальной (чаще регистровой) переменной. Вроде: void foo(float val) { u32 val32 = *(u32 *)&val; u32 res32 = 0x80000000; if (val32 != 0) res32 = (((val32 & 0x007FFFFF) >> 1) | 0x00400000) | ...; .... } Вот здесь (во второй строке), спрашивается, компилятору хватит информации не облажаться. Изменено 10 января, 2014 пользователем GetSmart Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 10 января, 2014 Опубликовано 10 января, 2014 · Жалоба Ну и как это связано с явным преобразованием идентификатора структуры? Разве при этом недостаточно информации о том, что "заказчик" желает взять именно её адрес? Никак. С тем вопросом уже разобрались. Более интересна ситуация, которую я нашёл у себя в исходниках, применения явного преобразования адреса к локальной (чаще регистровой) переменной. Как это - адрес у регистровой переменной? Ну, для PIC-ов, где все переменные - регистры, можно понять. А вы о каком процессоре говорите? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 10 января, 2014 Опубликовано 10 января, 2014 (изменено) · Жалоба Как это - адрес у регистровой переменной? Ну, для PIC-ов, где все переменные - регистры, можно понять. А вы о каком процессоре говорите? Там прикол в виртуальности этого адреса. По сути происходит/должно происходить интерпретация значения (битового представления) float как целочисленный u32. И это без использования временного union где-нибудь в оперативной памяти. Этот виртуальный адрес компилятор временно создаёт в своём личном формате хранения на этапе компиляции и только для себя, но передавать программе/программисту не обязан. А проблема заключается в явном преобразовании адреса с явным указанием (нового) адресного пространства. Никак. С тем вопросом уже разобрались. Обоснование Кейла не озвучено. Ещё интересно, как Кейл интерпретирует такое выражение: void *ptr; ptr = mb_cfg; // структура из начала темы Тоже, наверное, запретил. Хотя к массиву будет допустимо. Удостоверился в Кейл для глобальных переменных: - const (и static const, естественно) размещаются и используются из flash, - инициализированные переменные без квалификаторов (и volatile, естественно) при старте из flash переносятся в RAM и уже там используются. Кейлов много. Нужно указывать версию и для какого процессора. А при неуказании, сперва проверить на всех компиляторах Кейл для разных процессоров :) Изменено 10 января, 2014 пользователем GetSmart Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 10 января, 2014 Опубликовано 10 января, 2014 · Жалоба Ещё интересно, как Кейл интерпретирует такое выражение: void *ptr; ptr = mb_cfg; // структура из начала темы Тоже, наверное, запретил. Хотя к массиву будет допустимо. В середине темы по вашей просьбе я показал часть проекта с задачами - светодиодами, которая реально испытана на плате MCBSTM32 от Keil. Лично у меня нет никаких вопросов, которые стоило бы еще обсуждать в рамках заданной темы. upd. Нет, всплыл один вопросик. Выходит, константы лучше делать глобальными? Испортить их нельзя. А пригодиться они могут в разных функциях не раз. Обоснование Кейла не озвучено. Cогласно языку C. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Tarbal 4 10 января, 2014 Опубликовано 10 января, 2014 · Жалоба Что вы этим гениальным кодом хотите проверить? В ch сначала попадёт '5', затем в str1[0] запишется '5', затем в ch запишется '2', а строка ch=ch ничего не делает - она заоптимизируется почти всегда. Ах да, str1 и str2 будет размещено в ОЗУ. Если вы хотели str2 размещать во флэш, то надо было указать квалификатор __flash. Вы всегда отвечаете вопросом на вопрос? Может лучше посмотреть чем отгадывать? Удостоверился в Кейл для глобальных переменных: - const (и static const, естественно) размещаются и используются из flash, - инициализированные переменные без квалификаторов (и volatile, естественно) при старте из flash переносятся в RAM и уже там используются. Конкретно задавать нестандартные квалификаторы не вижу необходимости. О чем я и твержу. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrewlekar 0 10 января, 2014 Опубликовано 10 января, 2014 · Жалоба У кого есть IAR AVR? Для процессора с линейным адресным пространством (ARM, Cortex). Может уже хватит переливать из пустого в порожнее? То народ указатель на структуру от самой структуры отличить не может, то указатель на массив от самого массива, то общее адресное пространство от раздельного. Выходит, константы лучше делать глобальными? Испортить их нельзя. Если константа на самом деле где-то может пригодиться, то можете делать глобальной. Все подряд делать глобальными не стоит - экспортируется много символов и размываются интерфейсы у модулей. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться