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

 
 
5 страниц V  < 1 2 3 4 > »   
Reply to this topicStart new topic
> void const *argument, Что это?
Сергей Борщ
сообщение Jan 8 2014, 10:51
Сообщение #16


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(ViKo @ Jan 8 2014, 11:21) *
Мое мнение - для массива &mass и mass - одно и то же.
Не совсем. &mass[0] и mass - вот это одно и то же. Точнее mass неявно приводится к &mass[0].


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Jan 8 2014, 10:56
Сообщение #17


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Цитата(ViKo @ Jan 8 2014, 15:21) *
Проверьте на том, что имеете.
Мое мнение - для массива &mass и mass - одно и то же. Особенность языка.

В IARе я так много раз делал без замечаний. Но если 5-ый Keil ругается на явное преобразование адреса от имени структуры без амперсанда, то использование аналогичного синтаксиса к имени массива порождает другой глюк. Кейлу логично было бы запретить использование (void *)&mass. Иначе будут новые грабли.


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jan 8 2014, 11:10
Сообщение #18


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(GetSmart @ Jan 8 2014, 13:56) *
Кейлу логично было бы запретить использование (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; тоже не ругается!
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 8 2014, 18:11
Сообщение #19


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(ViKo @ Jan 8 2014, 13:10) *
На uint16_t *parr = (uint16_t *)&arr; тоже не ругается!
Естественно. Вы же делаете явное приведение типа. В этом случае каждый сам себе злобный Буратина, а компилятор умывает руки - если вы его просите о таком, значит знаете, чего хотите.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jan 8 2014, 18:30
Сообщение #20


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(Сергей Борщ @ Jan 8 2014, 21:11) *
Естественно. Вы же делаете явное приведение типа. В этом случае каждый сам себе злобный Буратина, а компилятор умывает руки - если вы его просите о таком, значит знаете, чего хотите.

Значит, компилятор "имеет представление" о том, что такое &arr. Почему же он неявное приведение не делает?
Ассемблерные команды получаются те же, что и для uint16_t *parr = arr;
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 9 2014, 01:29
Сообщение #21


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(ViKo @ Jan 8 2014, 20:30) *
Почему же он неявное приведение не делает?
Потому что таковы правила языка. Это называется "безопасность типов" (type safety). Он не даем вам случайно спутать теплое с мягким и мух с котлетами. Но и оставляет вам право сделать это, если вам это действительно нужно, через явное приведение типов.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Tarbal
сообщение Jan 9 2014, 02:47
Сообщение #22


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

Группа: Свой
Сообщений: 1 351
Регистрация: 21-05-10
Пользователь №: 57 439



В процессорах с Гарвардской архитектурой AVR, PIC, 8051 константы размещаются во флеше. Флеш расположен в другом адресном пространстве чем ОЗУ и используются другие ассемблерные команды для доступа. Разумно расположить константные массивы во флеше, поскольку если располагать их в ОЗУ, то будут использована и флеш тоже (откуда-то ведь будет инициализация читаться). Передавая такой параметр в функцию надо дать знать в каком пространстве памяти находится параметр, чтобы функция использовала правильные ассемблерные команды.
Для этого и используется слово const. Pic использует слово flash кажется, но это в микрочиповском компиляторе. С другими не работал не знаю.

Сообщение отредактировал Tarbal - Jan 9 2014, 02:48
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 9 2014, 07:28
Сообщение #23


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(Tarbal @ Jan 9 2014, 04:47) *
В процессорах с Гарвардской архитектурой 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() будет понимать - ей передали указатель на строку во флеше или на строку в ОЗУ?

Именно поэтому каждый компилятор добавляет расширения - вводит дополнительные квалификаторы для указания адресного пространства.

Цитата(Tarbal @ Jan 9 2014, 04:47) *
Передавая такой параметр в функцию надо дать знать в каком пространстве памяти находится параметр, чтобы функция использовала правильные ассемблерные команды.
Для этого и используется слово const. Pic использует слово flash кажется, но это в микрочиповском компиляторе.
Нет. слово const используется для другого. Как раз слово flash явлается расширением языка - квалификатором адресного пространства и используется именно для этого.

А вот в процессорах с единым адресным пространством (ARM, x86, MSP430) досуп к переменным во флеше или в ОЗУ на чтение одинаков, поэтому именно в них возможно указать линкеру размещать константные переменные во флеше не загружая копию в ОЗУ. А можно указать хранить в ОЗУ и все будет как у больших машин.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Herz
сообщение Jan 9 2014, 08:11
Сообщение #24


Гуру
******

Группа: Модераторы
Сообщений: 10 983
Регистрация: 23-11-05
Пользователь №: 11 287



Цитата(Сергей Борщ @ Jan 9 2014, 09:28) *
А вот в процессорах с единым адресным пространством (ARM, x86, MSP430) досуп к переменным во флеше или в ОЗУ на чтение одинаков, поэтому именно в них возможно указать линкеру размещать константные переменные во флеше не загружая копию в ОЗУ. А можно указать хранить в ОЗУ и все будет как у больших машин.

А каким образом это делается? Буквально в двух словах, если можно.
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jan 9 2014, 08:16
Сообщение #25


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(Сергей Борщ @ Jan 9 2014, 10:28) *
А вот в процессорах с единым адресным пространством (ARM, x86, MSP430) досуп к переменным во флеше или в ОЗУ на чтение одинаков, поэтому именно в них возможно указать линкеру размещать константные переменные во флеше не загружая копию в ОЗУ. А можно указать хранить в ОЗУ и все будет как у больших машин.

Есть способ - указать квалификатор static.
Код
static const uint8_t *SourTxt[] = {"Кан1", "Кан2"};

В ОЗУ этих строк не будет. Сразу будут читаться из флэш программы.
Go to the top of the page
 
+Quote Post
andrewlekar
сообщение Jan 9 2014, 10:17
Сообщение #26


Знающий
****

Группа: Участник
Сообщений: 837
Регистрация: 8-02-07
Пользователь №: 25 163



При чём тут static вообще? На ARMах const в определении переменной заставляет компилятор (и линкер) размещать её во флэше. На AVR такое не работало из-за раздельного адресного пространства.
Go to the top of the page
 
+Quote Post
XVR
сообщение Jan 9 2014, 10:20
Сообщение #27


Гуру
******

Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847



Использование ключевых слов static и/или const для управления размещением данных (будь то flash или еще что) - вещь на 100% зависящая от конкретного компилятора. Стандарт С/С++ вообще не знает о том, что такое flash и как в нее помещать данные sm.gif

Поэтом, прежде чем советовать что то типа
Цитата
Есть способ - указать квалификатор static.
В ОЗУ этих строк не будет. Сразу будут читаться из флэш программы.
стоит указать, для каких именно компиляторов это справедливо
Go to the top of the page
 
+Quote Post
andrewlekar
сообщение Jan 9 2014, 10:27
Сообщение #28


Знающий
****

Группа: Участник
Сообщений: 837
Регистрация: 8-02-07
Пользователь №: 25 163



Цитата
для каких именно компиляторов

Ни для каких. static очевидно может изменяться во время выполнения программы и не может быть размещён во flash.
const размещает переменные во flash независимо от квалификатора static - актуально для IAR для ARM.
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jan 9 2014, 10:36
Сообщение #29


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(XVR @ Jan 9 2014, 13:20) *
Поэтом, прежде чем советовать что то типа
стоит указать, для каких именно компиляторов это справедливо

Для компилятора, входящего в состав Keil uVision. Пользуюсь этими квалификаторами.
О каком компиляторе идет речь, видно в теме неоднократно.


Цитата(andrewlekar @ Jan 9 2014, 13:27) *
static очевидно может изменяться во время выполнения программы и не может быть размещён во flash.
const размещает переменные во flash независимо от квалификатора static - актуально для IAR для ARM.

static const
Строка просто const из flash переписывается в ОЗУ, и уже из ОЗУ используется в функции. Лично сталкивался. И получал на форуме совет. И от кого, помню.
Go to the top of the page
 
+Quote Post
andrewlekar
сообщение Jan 9 2014, 10:40
Сообщение #30


Знающий
****

Группа: Участник
Сообщений: 837
Регистрация: 8-02-07
Пользователь №: 25 163



Что, вашему компилятору не хватает ума разместить глобальную переменную во флэше? Или вы просто не пробовали?
Go to the top of the page
 
+Quote Post

5 страниц V  < 1 2 3 4 > » 
Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 25th July 2025 - 13:28
Рейтинг@Mail.ru


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