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

 
 
5 страниц V   1 2 3 > »   
Reply to this topicStart new topic
> void const *argument, Что это?
ViKo
сообщение Jan 6 2014, 19:06
Сообщение #1


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

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



В Keil CMSIS-RTOS RTX в параметрах задач указано:
Код
void job1 (void const *arg)

Что это, зачем? Писал, не задумываясь. Теперь хочу просветиться.
Go to the top of the page
 
+Quote Post
megajohn
сообщение Jan 6 2014, 19:57
Сообщение #2


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

Группа: Свой
Сообщений: 1 080
Регистрация: 16-11-04
Из: СПб
Пользователь №: 1 143



ну к примеру у вас на контроллере два UART

и в одном проекте на modbus реализован на UART0 9600 а на UART1 модем AT 115200

а в другом проекте modbus реализован на UART1 19200 а на UART0 модем AT 36000

а задачи одинаковые.

тогда для проекта 1

typedef struct{
int port;
int speed;
}Suart_init;

const Suart_init mb_cfg = { 0, 9600 };
task_start( mb_task, ..., (void*)mb_cfg );

где

void mb_task( void const* arg )
{
Suart_init* arg_p = (Suart_init*)arg;
uart_open( arg_p->port, arg_p->speed );
...
}



то есть как реально в RTX синтаксис вызова не в курсе, но суть передал - вызов задач с конкретными параметрами.


--------------------
Марс - единственная планета, полностью населенная роботами (около 7 штук).
Go to the top of the page
 
+Quote Post
kosyak©
сообщение Jan 6 2014, 20:14
Сообщение #3


Частый гость
**

Группа: Свой
Сообщений: 179
Регистрация: 1-10-07
Из: НЧ
Пользователь №: 30 966



Вот зачем оно конст...?
Go to the top of the page
 
+Quote Post
megajohn
сообщение Jan 6 2014, 20:18
Сообщение #4


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

Группа: Свой
Сообщений: 1 080
Регистрация: 16-11-04
Из: СПб
Пользователь №: 1 143



если оно будет на стеке, то по моменту запуска самой задачи естветсвено всё уплывет.

то есть так нельзя
Suart_init mb_cfg = { 0, 9600 };
task_start( mb_task, ..., (void*)mb_cfg );

а так можно
const Suart_init mb_cfg = { 0, 9600 };
task_start( mb_task, ..., (void*)mb_cfg );

или так
static Suart_init mb_cfg = { 0, 9600 };
task_start( mb_task, ..., (void*)mb_cfg );


--------------------
Марс - единственная планета, полностью населенная роботами (около 7 штук).
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jan 6 2014, 20:35
Сообщение #5


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

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



Цитата(megajohn @ Jan 6 2014, 22:57) *
то есть как реально в RTX синтаксис вызова не в курсе, но суть передал - вызов задач с конкретными параметрами.

Спасибо! Понял. Проверил в действии. Работает.

Нужно поправить - брать адрес структуры.
Код
task_start( mb_task, ..., (void*)&mb_cfg );
Go to the top of the page
 
+Quote Post
kosyak©
сообщение Jan 6 2014, 20:40
Сообщение #6


Частый гость
**

Группа: Свой
Сообщений: 179
Регистрация: 1-10-07
Из: НЧ
Пользователь №: 30 966



тогда уж
task_start( mb_task, ..., (void const*)&mb_cfg );
sm.gif
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Jan 6 2014, 23:38
Сообщение #7


.
******

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



Вообще-то компилятор должен "съедать" этот параметр при вызове функции и без явного преобразования. Как и для параметра "void *" компилятор должен принимать указатель на любой неконстантный объект из соответствующего адресного пространства. Если отказывается, то это наверное плохой компилятор. Без явного преобразования очевидно, что безопаснее.

Цитата(ViKo @ Jan 7 2014, 02:35) *
Нужно поправить - брать адрес структуры.

Какая разница в данном случае, с амперсандом или без? В случае когда голый идентификатор структуры без указания поля. Однозначнее, конечно, было бы с амперсандом, но на данный момент в Си оба варианта вроде бы одинаковые.

Цитата(megajohn @ Jan 7 2014, 02:18) *
если оно будет на стеке, то по моменту запуска самой задачи естветсвено всё уплывет.

Квалификатор const не запретит передачу локальной переменной. Не встать на грабли - забота программиста. const в параметре "проявит себя" только внутри тела функции, когда этот указатель без явного преобразования будет передан параметром или присвоен другому типизированному указателю на константу.

Цитата(megajohn @ Jan 7 2014, 02:18) *
то есть так нельзя
Suart_init mb_cfg = { 0, 9600 };
task_start( mb_task, ..., (void*)mb_cfg );

а так можно
const Suart_init mb_cfg = { 0, 9600 };
task_start( mb_task, ..., (void*)mb_cfg );

Второй вариант тоже будет на стеке. Просто менять его значения нельзя будет.

Сообщение отредактировал GetSmart - Jan 7 2014, 02:22


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


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

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



Цитата(GetSmart @ Jan 7 2014, 02:38) *
Какая разница в данном случае, с амперсандом или без? В случае когда голый идентификатор структуры без указания поля. Однозначнее, конечно, было бы с амперсандом, но на данный момент в Си оба варианта вроде бы одинаковые.

Возможно, в других языках варианты одинаковые. Но не в С. В C можно структуру передавать в функцию, именно, по значению, а не по ссылке. Т.е., имя структуры не есть ее адрес. В отличие от массива.
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Jan 7 2014, 10:08
Сообщение #9


.
******

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



Цитата(ViKo @ Jan 7 2014, 14:50) *
Возможно, в других языках варианты одинаковые. Но не в С.

Чем отличается результат двух вариантов выражений со структурами ниже?
Код
(void*)&mb_cfg
и
(void*)mb_cfg

Если отличаются, то в каких компиляторах.

Идентификатор/имя массива тоже не является адресом его первого элемента. Иначе выражение &mass было бы аналогом &(&mass[0]). Взятие адреса от адреса в Си допустимо?

Сообщение отредактировал GetSmart - Jan 7 2014, 10:18


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


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

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



Цитата(GetSmart @ Jan 7 2014, 13:08) *
Чем отличается результат двух вариантов выражений со структурами ниже?
Код
(void*)&mb_cfg
и
(void*)mb_cfg

Если отличаются, то в каких компиляторах.

Тем, что второй вариант не компилируется.
Keil V5.1.0
source\exsUSB.c(164): error: #171: invalid type conversion
Led9_id = osThreadCreate(osThread(Led_thread), (void *)led9);
А в каком компиляторе работают оба? rolleyes.gif
Go to the top of the page
 
+Quote Post
megajohn
сообщение Jan 7 2014, 10:20
Сообщение #11


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

Группа: Свой
Сообщений: 1 080
Регистрация: 16-11-04
Из: СПб
Пользователь №: 1 143



Цитата(GetSmart @ Jan 7 2014, 03:38) *
Квалификатор const не запретит передачу локальной переменной. Не встать на грабли - забота программиста. const в параметре "проявит себя" только внутри тела функции, когда этот указатель без явного преобразования будет передан параметром или присвоен другому типизированному указателю на константу.

не знаю как в высших материях, но в дизамсе передается просто адрес. Задача компилятора - ругатся при попытке записи по const*

Цитата(GetSmart @ Jan 7 2014, 03:38) *
Второй вариант тоже будет на стеке. Просто менять его значения нельзя будет.


если это AVR то будет во флеше, если ARM то как указано в линкере ROM_region. А в других архитектурах как решит компиляторы, но размещать const на стеке вызывающей задачи - сомнительно.

Цитата(ViKo @ Jan 7 2014, 00:35) *
Нужно поправить - брать адрес структуры.
Код
task_start( mb_task, ..., (void*)&mb_cfg );


да, мой косяк. Вместо компилятора под руками была текила, и это зло вчера меня победило


--------------------
Марс - единственная планета, полностью населенная роботами (около 7 штук).
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Jan 7 2014, 10:38
Сообщение #12


.
******

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



Цитата(ViKo @ Jan 7 2014, 16:18) *
Led9_id = osThreadCreate(osThread(Led_thread), (void *)led9);
А в каком компиляторе работают оба? rolleyes.gif

Предъявите объявление led9.
Проверьте для корректности все предыдущие версии Кейла. Если раньше оба варианта допускались, то как разработчики это обосновали и обосновали ли?

Цитата(megajohn @ Jan 7 2014, 16:20) *
если это AVR то будет во флеше,

То есть от компилятора не зависит?

Цитата(megajohn @ Jan 7 2014, 16:20) *
не знаю как в высших материях, но в дизамсе передается просто адрес. Задача компилятора - ругатся при попытке записи по const*

Я имел ввиду "проявит себя" на этапе компиляции. По сути то же самое. Вне тела функции наличие квалификатора const никак не ограничивает передачу параметров по сравнению с вариантом без квалификатора const (в прототипе функции).

Сообщение отредактировал GetSmart - Jan 7 2014, 10:50


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


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

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



Цитата(GetSmart @ Jan 7 2014, 13:29) *
Предъявите объявление led9.

CODE

typedef struct {
uint16_t leds;
uint32_t dels;
} thread_init;

const thread_init led8 = {0x0100, 500};
const thread_init led9 = {0x0200, 498};
const thread_init led10 = {0x0400, 496};
const thread_init led11 = {0x0800, 494};
const thread_init led12 = {0x1000, 492};
const thread_init led13 = {0x2000, 490};
const thread_init led14 = {0x4000, 488};
const thread_init led15 = {0x8000, 486};

void Led_thread(void const *arg); // прототип

osThreadId Led8_id;
osThreadId Led9_id;
osThreadId Led10_id;
osThreadId Led11_id;
osThreadId Led12_id;
osThreadId Led13_id;
osThreadId Led14_id;
osThreadId Led15_id;

osThreadDef(Led_thread, osPriorityNormal, 1, 0);

int32_t main(void)
{
...
Led8_id = osThreadCreate(osThread(Led_thread), (void *)&led8);
Led9_id = osThreadCreate(osThread(Led_thread), (void *)&led9);
Led10_id = osThreadCreate(osThread(Led_thread), (void *)&led10);
Led11_id = osThreadCreate(osThread(Led_thread), (void *)&led11);
Led12_id = osThreadCreate(osThread(Led_thread), (void *)&led12);
Led13_id = osThreadCreate(osThread(Led_thread), (void *)&led13);
Led14_id = osThreadCreate(osThread(Led_thread), (void *)&led14);
Led15_id = osThreadCreate(osThread(Led_thread), (void *)&led15);
...
}

void Led_thread(void const *arg)
{
while (true) {
GPIOB->BSRR = ((thread_init *)arg)->leds;
osDelay(((thread_init *)arg)->dels);
GPIOB->BSRR = ((thread_init *)arg)->leds << 16;
osDelay(((thread_init *)arg)->dels);
}
}

Go to the top of the page
 
+Quote Post
GetSmart
сообщение Jan 8 2014, 06:38
Сообщение #14


.
******

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



Цитата(ViKo @ Jan 7 2014, 16:18) *
Тем, что второй вариант не компилируется.
Keil V5.1.0

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

Жаль, в Си нет операторов детипизации указателей, сохраняя исходное адресное пространство. В идеале ещё как-то наследующих выравнивание и другие атрибуты. Вручную для безопасной работы приходится объявлять указатель на void и потом его присваивать к другому типизированному указателю.

Сообщение отредактировал GetSmart - Jan 8 2014, 06:48


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


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

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



Цитата(GetSmart @ Jan 8 2014, 09:38) *
А (void *)&mass скомпилируется, если это идентификатор массива? Кейла 5-ого под рукой нет чтобы проверить.

Проверьте на том, что имеете.
Мое мнение - для массива &mass и mass - одно и то же. Особенность языка.
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 17:45
Рейтинг@Mail.ru


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