Сергей Борщ 134 8 января, 2014 Опубликовано 8 января, 2014 · Жалоба Мое мнение - для массива &mass и mass - одно и то же.Не совсем. &mass[0] и mass - вот это одно и то же. Точнее mass неявно приводится к &mass[0]. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 8 января, 2014 Опубликовано 8 января, 2014 · Жалоба Проверьте на том, что имеете. Мое мнение - для массива &mass и mass - одно и то же. Особенность языка. В IARе я так много раз делал без замечаний. Но если 5-ый Keil ругается на явное преобразование адреса от имени структуры без амперсанда, то использование аналогичного синтаксиса к имени массива порождает другой глюк. Кейлу логично было бы запретить использование (void *)&mass. Иначе будут новые грабли. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 8 января, 2014 Опубликовано 8 января, 2014 · Жалоба Кейлу логично было бы запретить использование (void *)&mass. Наверное, так оно и есть. Проверил. Получил. uint16_t arr[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; uint16_t *parr = &arr; source\Exercises.c(159): error: #144: a value of type "uint16_t (*)[10]" cannot be used to initialize an entity of type "uint16_t *" На uint16_t *parr = &arr[0]; не ругается, естественно. На uint16_t *parr = (uint16_t *)&arr; тоже не ругается! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 134 8 января, 2014 Опубликовано 8 января, 2014 · Жалоба На uint16_t *parr = (uint16_t *)&arr; тоже не ругается!Естественно. Вы же делаете явное приведение типа. В этом случае каждый сам себе злобный Буратина, а компилятор умывает руки - если вы его просите о таком, значит знаете, чего хотите. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 8 января, 2014 Опубликовано 8 января, 2014 · Жалоба Естественно. Вы же делаете явное приведение типа. В этом случае каждый сам себе злобный Буратина, а компилятор умывает руки - если вы его просите о таком, значит знаете, чего хотите. Значит, компилятор "имеет представление" о том, что такое &arr. Почему же он неявное приведение не делает? Ассемблерные команды получаются те же, что и для uint16_t *parr = arr; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 134 9 января, 2014 Опубликовано 9 января, 2014 · Жалоба Почему же он неявное приведение не делает?Потому что таковы правила языка. Это называется "безопасность типов" (type safety). Он не даем вам случайно спутать теплое с мягким и мух с котлетами. Но и оставляет вам право сделать это, если вам это действительно нужно, через явное приведение типов. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Tarbal 4 9 января, 2014 Опубликовано 9 января, 2014 (изменено) · Жалоба В процессорах с Гарвардской архитектурой AVR, PIC, 8051 константы размещаются во флеше. Флеш расположен в другом адресном пространстве чем ОЗУ и используются другие ассемблерные команды для доступа. Разумно расположить константные массивы во флеше, поскольку если располагать их в ОЗУ, то будут использована и флеш тоже (откуда-то ведь будет инициализация читаться). Передавая такой параметр в функцию надо дать знать в каком пространстве памяти находится параметр, чтобы функция использовала правильные ассемблерные команды. Для этого и используется слово const. Pic использует слово flash кажется, но это в микрочиповском компиляторе. С другими не работал не знаю. Изменено 9 января, 2014 пользователем Tarbal Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 134 9 января, 2014 Опубликовано 9 января, 2014 · Жалоба В процессорах с Гарвардской архитектурой AVR, PIC, 8051 константы размещаются во флеше.Ну вот где вы такое видели применительно к языку C в реальном мире? Квалификатор const лишь дает гарантию, что компилятор не допустит изменения переменной с таким квалификатором. И никоим образом не влияет на адресное пространство. Если вы объявили переменную с квалификатором const - под нее точно так же будет выделено место в ОЗУ. вот вам простой пример: char string1[] = " string1"; char const string2[] = "string2"; void print_string(char const * string) // const тут гарантирует, что функция не изменит переданную ей строку { ......... string[0] = '+'; // компилятор даст по рукам. В объявлении параметра мы обещали, что не будем его менять } void empty_string(char * string) // а вот тут гарантий нет, переданная строка может быть изменена. { ......... string[1] = '+'; // пожалуйста } void test() { print_string(string1); // да без проблем, в соответствии с правилами языка print_string(string2); // тоже запросто empty_string(string1); // легко empty_string(string2); // нифига. const в объявлении string2 запрещает, функция может модифицировать строку string1[0] = "!"; // да, пожалуйста string2[0] = "x"; // а вот фиг } А теперь объясните, каким образом print_string() будет понимать - ей передали указатель на строку во флеше или на строку в ОЗУ? Именно поэтому каждый компилятор добавляет расширения - вводит дополнительные квалификаторы для указания адресного пространства. Передавая такой параметр в функцию надо дать знать в каком пространстве памяти находится параметр, чтобы функция использовала правильные ассемблерные команды. Для этого и используется слово const. Pic использует слово flash кажется, но это в микрочиповском компиляторе. Нет. слово const используется для другого. Как раз слово flash явлается расширением языка - квалификатором адресного пространства и используется именно для этого. А вот в процессорах с единым адресным пространством (ARM, x86, MSP430) досуп к переменным во флеше или в ОЗУ на чтение одинаков, поэтому именно в них возможно указать линкеру размещать константные переменные во флеше не загружая копию в ОЗУ. А можно указать хранить в ОЗУ и все будет как у больших машин. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Herz 5 9 января, 2014 Опубликовано 9 января, 2014 · Жалоба А вот в процессорах с единым адресным пространством (ARM, x86, MSP430) досуп к переменным во флеше или в ОЗУ на чтение одинаков, поэтому именно в них возможно указать линкеру размещать константные переменные во флеше не загружая копию в ОЗУ. А можно указать хранить в ОЗУ и все будет как у больших машин. А каким образом это делается? Буквально в двух словах, если можно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 9 января, 2014 Опубликовано 9 января, 2014 · Жалоба А вот в процессорах с единым адресным пространством (ARM, x86, MSP430) досуп к переменным во флеше или в ОЗУ на чтение одинаков, поэтому именно в них возможно указать линкеру размещать константные переменные во флеше не загружая копию в ОЗУ. А можно указать хранить в ОЗУ и все будет как у больших машин. Есть способ - указать квалификатор static. static const uint8_t *SourTxt[] = {"Кан1", "Кан2"}; В ОЗУ этих строк не будет. Сразу будут читаться из флэш программы. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrewlekar 0 9 января, 2014 Опубликовано 9 января, 2014 · Жалоба При чём тут static вообще? На ARMах const в определении переменной заставляет компилятор (и линкер) размещать её во флэше. На AVR такое не работало из-за раздельного адресного пространства. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xvr 12 9 января, 2014 Опубликовано 9 января, 2014 · Жалоба Использование ключевых слов static и/или const для управления размещением данных (будь то flash или еще что) - вещь на 100% зависящая от конкретного компилятора. Стандарт С/С++ вообще не знает о том, что такое flash и как в нее помещать данные :) Поэтом, прежде чем советовать что то типа Есть способ - указать квалификатор static. В ОЗУ этих строк не будет. Сразу будут читаться из флэш программы. стоит указать, для каких именно компиляторов это справедливо Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrewlekar 0 9 января, 2014 Опубликовано 9 января, 2014 · Жалоба для каких именно компиляторов Ни для каких. static очевидно может изменяться во время выполнения программы и не может быть размещён во flash. const размещает переменные во flash независимо от квалификатора static - актуально для IAR для ARM. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 9 января, 2014 Опубликовано 9 января, 2014 · Жалоба Поэтом, прежде чем советовать что то типа стоит указать, для каких именно компиляторов это справедливо Для компилятора, входящего в состав Keil uVision. Пользуюсь этими квалификаторами. О каком компиляторе идет речь, видно в теме неоднократно. static очевидно может изменяться во время выполнения программы и не может быть размещён во flash. const размещает переменные во flash независимо от квалификатора static - актуально для IAR для ARM. static const Строка просто const из flash переписывается в ОЗУ, и уже из ОЗУ используется в функции. Лично сталкивался. И получал на форуме совет. И от кого, помню. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrewlekar 0 9 января, 2014 Опубликовано 9 января, 2014 · Жалоба Что, вашему компилятору не хватает ума разместить глобальную переменную во флэше? Или вы просто не пробовали? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться