Просмотр полной версии : Pointer-константа: как инициализировать?
Хочу сделать константный указатель на данные разных типов:
VAR_GLOBAL CONSTANT
VAR1: DWORD := 100;
Ptr1: POINTER TO DWORD := ADR( VAR1);
Ptr2: POINTER TO DWORD := ADR( VAR2);
Ptr3: POINTER TO DWORD := ADR( VAR3);
END_VAR
VAR_GLOBAL RETAIN
VAR2: DWORD := 1;
END_VAR
VAR_GLOBAL
VAR3: DWORD := 1;
END_VAR
То есть, пойнтеры 1, 2 и 3 указывают на данные типа CONSTANT, RETAIN и обычные переменные. И эти пойнтеры по смыслу никогда не изменяются, т.е. представляют сами по себе данные типа CONSTANT.
Как их инициализировать? Компилятор ругается на все три строчки:
Неверное начальное значение
Аналогичное присвоение в программе работает на ура. Ну, там просто функция подставляется ADR() и она все делает чики-пики.
А как же компилятору сказать "адрес переменной VAR1"? Читаю и не нахожу...
Спасибо!
Малышев Олег
14.12.2010, 17:00
1) ADR - runtime функция. - вызывайте в программе
2) По страшному секрету - финальная линковка программы идет в контроллере и ПЛК не известно таких наворотов как в линкерах больших компиляторов.
то есть, в кдс присвоить указателю-константе значение адреса переменной в принципе нельзя?
Филоненко Владислав
14.12.2010, 18:32
только хакерским трюком, сначала узнать адрес через Adr, а затем, циферками, его задать :)
Указатели были "искусственно пришиты" к МЭК языкам. По хорошему их чем меньше используешь тем надёжнее программа.
понял, спасибо!
использовать все же буду, но без хакерства :) у меня недостаточная квалификация для хакерства.
в общем-то обходной маневр мне подсказали на этом форуме. только там получается, что целый массив структур с абсолютно известными и неизменными нормальному компилятору значениями всех элементов приходится размещать в озу и инициализировать после старта. это должно быть пофиг, но пока в проге есть баги, иногда приводит к неверной иницилизации. вот я и подумал, баги-то постепенно устраню (как говорится, до предпоследнего включительно), а прописать константный массив как-то надежнее.
ну, не получилось :(
... по хорошему их чем меньше используешь тем надёжнее программа.
надежность кода зависит не от количества указателей, а от самого кодера.и если программа начинает жить загадочной жизнью, то хоть вообще выкинуть все поинтеры - загадки останутся.
а прописать константный массив как-то надежнее.
ну, не получилось :(
У меня в щите управления, с другой стороны стены, перфоратором контактор просверлили. А уж куда константнее.
Все мнения о не "солидности" инициализации в коде - имхо мнения, мягко скажу, не уверенных в своем собственном коде.
все мнения о не "солидности" инициализации в коде - имхо мнения, мягко скажу, не уверенных в своем собственном коде.
зачем так категорично? я знаю мнение уважаемых мною программистов, которые говорят, что это "фи". иное дело, в чем чел работает. в яве нас бы засмеяли. если в кдс вот так уж есть, то куда ж деться. а стремиться к красоте нужно всегда, имхо.
кстати, тут ветер рядом веял, напомнил мне о вашем споре по поводу работы со временем. вот и в связи с этим хочу заметить: а неплохо бы, чтобы в кдс была возможность инициализировать константный указатель. выносить в отдельную тему с заголовком "к и.петрову" я не буду, подожду, как он на временные споры отреагирует. но вообще - почему бы и нет? как-то же принимаются решения о внесении изменений. и обсуждения на форумах могут поспособствовать.
Филоненко Владислав
15.12.2010, 11:06
надежность кода зависит не от количества указателей, а от самого кодера.и если программа начинает жить загадочной жизнью, то хоть вообще выкинуть все поинтеры - загадки останутся.
Вы не правы.
Указатель - это адрес переменной. Переменная, на которую указывает указатель не поддается контролю ни в момент компиляции, ни в момент исполнения. Исключение - архитектура "Эльбрус" :D
В этом суть проблемы. Мало кто перед каждым! использованием указателя проверяет его хотя-бы на NULL, не говоря уже о более сложных проверках. А для обычных переменных, с жестким адресом, все гораздо проще и надежнее.
Для того, чтобы сделать указатель ну хоть как-нибудь контролируемым, придумали ссылки (по сути константный указатель без разименовывания) для статического контроля и всякие сложные вещи типа boost для динамического.
Как говорится, и хочется, и колется.
Вы не правы.
Указатель - это адрес переменной. Переменная, на которую указывает указатель не поддается контролю ни в момент компиляции, ни в момент исполнения. Исключение - архитектура "Эльбрус"
...
Как говорится, и хочется, и колется.
Если нельзя, но очень хочется :)
Не знаю я про Ваши Эльбрусы... Не понимаю, почему в принципе нельзя знать адрес переменной при компилировании (если уж точно, то при линковании) - и присвоить переменной, которую я объявил *имя (по-сишному), значение, равное адресу этой переменной. Если так делает Си, то почему НИЗЗЯ другим?
Даже, если в ПЛК грузится перемещаемая программа - разве не выисляются в момент ее размещения истинные адреса всех данных?
И, независимо от возможности того, о чем я только что сказал, объявление переменной (в данном случае - указателя) типом CONST вполне может помочь компилятору проконтролировать ситуацию, когда эту переменную-указатель кто-то пытается изменить. Ну, и нам сказать об этом. Т.е. объявление
VAR CONSTANT
ptr: POINTER TO DWORD;
END_VAR
...в этом именно смысле - полезно? Тогда почему не добавить возможность инициализации этого пойнтера?
Прошу понять, я понял и принял, что в КДС такой возможности нет. Не могу понять, почему уважаемый Владислав пытается убедить нас, что это есть благо...
тема ушла :)
ну и зря. конечно, я внимательно прислушиваюсь к твоему мнению. конечно, я понимаю, что пафоса та тема не стоит. но - почему не поговорить спокойно?
я вот про пойнтеры размышлял, пока спиртное к праздникам закупал :) смотри, пойнтер и целое - суть разные типы данных. сумма (значенией) двух указателей - бессмысленна. а вот разность указателей - вполне понятная величина, определяющая, например, количество элементов массива между этими указателями.
также указатель + целое - указывает на данные, расположенные на некотором расстоянии от того, куда направлен указатель.
делаю аналогию с типом дата и целое. сумма двух дат - бессмысленна. а разность - скока нам дней :)
так же дата + целое = новая дата. так чем это полохо? только тем, что в нынешней версии кдв его нет?
как ты пишешь, прокол в кдс не умаляет нашего к система почтения. согласен!
но и отсутствие чего-то в кдс не умаляет моего уважения к возможности реализации этого чего-то :)
TO "DRVLAS" : не ужели вы УВАЖАЕМЫЙ не поняли - CoDeSys v2.3 давно закрыт, заброшен как пройденный этап. Это примерно то же, что просить добавить что то в ФОРТРАН. Хоть кто то помнит что это такое.
Я еще раз призываю вспомнить чему их учили в школе, институте, в НИИ. КДС 2.3 никто уже не развивает, поддерживают, чтобы не упал. Это истина. И пожалейте ПЕТРОВА он хороший человек и отвечает за свои слова. Я видел исходники КДС 2.3 .
TO "DRVLAS" : не ужели вы УВАЖАЕМЫЙ не поняли - CoDeSys v2.3 давно закрыт, заброшен как пройденный этап
Да как мне понять? Я новичек в этом. Я ничего не знаю (и пока не берусь узнавать) о версии 3. Я уверен, что мою шарабайку можно запрограммировать и не выходя за пределы 2.3... Мне говорили уважаемые мною люди здесь на форуме, что КСД - просто потрясная штука. Имея в виду, конечно, 2.3.
Так в чем проблема?
Если Вы настолько приближены к истокам, что знаете товарища Петрова, знаете, что
он хороший человек и отвечает за свои слова
и даже видели
исходники КДС 2.3 .
- так это же замечательно! Расскажите, изменится ли поднятый мною вопрос в версии 3. Ну, если знаете, конечно.
А я пока буду в своем песочнике играться. Люблю я это дело...
Дмитрий Егоренков
16.12.2010, 11:50
зачем? зачем вам нужны глобальные константные указатели?
почему вы не хотите напрямую использовать те сущности, на которые они указывают?
Филоненко Владислав
16.12.2010, 12:06
TO "DRVLAS" : не ужели вы УВАЖАЕМЫЙ не поняли - CoDeSys v2.3 давно закрыт, заброшен как пройденный этап. Это примерно то же, что просить добавить что то в ФОРТРАН. Хоть кто то помнит что это такое.
Я еще раз призываю вспомнить чему их учили в школе, институте, в НИИ. КДС 2.3 никто уже не развивает, поддерживают, чтобы не упал. Это истина. И пожалейте ПЕТРОВА он хороший человек и отвечает за свои слова. Я видел исходники КДС 2.3 .
К сожалению, 3-й кодесис еще не догнал 2.3 по функционалу. Через годик, наверное, догонит. Так что 2.3 еще долгое время будет актуален, хотя бы из-за числа ПЛК, программ и специалистов.
зачем? зачем вам нужны глобальные константные указатели?
Потому, что на этапе компиляции я не могу знать, к какой сущности я обращусь. Собственно, это и есть причина появления указателей в языках программирования, ИМХО. Это похоже на массивы - ведь удобно использовать A[n] при разном n, вместо того, чтобы обращаться к каждому элементу по прямому адресу.
А пойнтеры и массивы - почти одно и то же.
О своей задаче я немного говорил здесь (http://owen.ru/forum/showthread.php?t=9285).
В той структуре описателей переменной добавился указатель на саму переменную.
Так что потребность есть. Иное дело, что при расположении массива структур (а в каждой из них - и указателей) в обычной памяти задача уже решена и все прекрасно работает. Спасибо Валенку. Потом подумал об альтернативе - ну, нет ее в КДС.
Ладненько, не страшно. Еще раз - я удовлетворен. Не надо меня шпынять, что упорно требую от авторов КДС немедленных изменений :) Только даю сигналы...
Дмитрий Егоренков
16.12.2010, 17:49
Потому, что на этапе компиляции я не могу знать, к какой сущности я обращусь.
тогда повторю вопрос. зачем вам глобальные константные указатели, значения которых вам прекрасно известны, и которые не могут измениться на этапе выполнения?
О своей задаче я немного говорил здесь (http://owen.ru/forum/showthread.php?t=9285).
в приведенной ссылке, как и в этой ветке, есть только ваши попытки решить какую-то неизвестную нам задачу, но не сама задача.
Хорошо. Там действительно не все понятно, я думаю.
Итак, у меня в программе есть большое количество переменных (я их называю параметрами), к которым я боращаюсь обычным образом. Беру их значение, использую в выражениях, записываю, сохраняю в RETAIN или нет - все чин чинарем.
Но именно эти переменные-параметры объединяет то, что в определенных функциях (очень иногда, кстати) обращаться к ним удобно через индекс, как к элементам массива. И при этом существует ряд свойств каждого параметра, которые задаются еще до компиляции. Ну, например, предельные значения параметра. Эти свойства извлекать тогда тоже удобно из массива - по тому же индексу.
Так вот, есть массив структур, содержащих все свойства каждого параметра:
TYPE PARSCRIPT :
STRUCT
Numb: WORD;
Typ: PARTYPE;
Point: BYTE;
Mdf: RW_ACCESS;
Node: OWNER_NODE;
Mini: DINT;
Maxi: DINT;
Ptr: POINTER TO DWORD;
END_STRUCT
END_TYPE
Вот объявление этого массива:
VAR_GLOBAL
apsPar: ARRAY [0..MAX_PAR_INDX] OF PARSCRIPT;
END_VAR
Используя где-то в проге apsPar[i].Ptr, я могу извлечь самое переменную или записать ее на свое место. По указателю, коим является элемент структуры apsPar[i].Ptr.
Как видите, указатели-то указывают на адрес переменной, вполне фиксированный. Вот я и говорил о том, что объявить массив структур вполне можно было с CONSTANT.
Оказалось, что можно. Но только инициализировать пойнтер значением адреса данных (любых - хоть констант, хоть переменных) - нельзя.
Сам не знаю, зачем так подробно поясняю. Все равно сейчас Вы воскликнете "Проект - в студию!"
И что после этого? У Вас есть предположения, как же объявить константный указатель? Отвлекаясь от того, нафига он мне :)
Дмитрий Егоренков
17.12.2010, 15:33
вы опять описываете реализацию, а не задачу, ну да ладно.
в общем, указатели вам нужны внутри структур, это я могу понять. а против ограничений платформы не попрешь -- придется вам инициализировать указатели при запуске программы.
ну, как умею.
против ограничений платформы не попрешь -- придется вам инициализировать указатели при запуске программы.
так и делаю. тешу себя тем, что плюсов у выбранной платформы очень много и они для меня важнее.
вчера меня так уговаривали попробовать другие контроллеры (и российские есть), в том числе и с линухом на борту, и с экраном и без, и манюсенькие, и лишь чуть дороже плк100...
на шару ведь дают, только пробуй. но почему-то кдс мне нравится (сейчас пока могу сказать - не на уровне понимания, а так, за красивые глазки) и я с гордым видом отказался :)
надо довести хоть первый проект до конца, тогда можно оглядеться еще раз.
-- придется вам инициализировать указатели при запуске программы.
Была бы определённая функция (типа Setup как в Arduino) выполняемая один раз при старте контроллера, и засорять инициализацией PLC_PRG не пришлось бы..
Да и на ФБ конструкторов не хватает, и метод инициализации для них не сделаешь, так как методам незя аргументы передать... Усё приходится делать через ЖЖЖ..
о! так давайте спрошу.
я думаю, что, если в проекте есть программа Sfc, то в ней шаг Init - выполняется единожды?
а второй путь, который я понимаю, это проверять некий бит, инициализуемый нулем при старте программы. и по нему выполнять разовые процедур, не забыв его тоже взвести.
это, конечно, известно. пишу потому, что вот это свойство плк замечать пропадание питания и прятать свои переменные на 10 минут - меня смущает. ведь с ними сохраняется и тот бит. а потом у меня (с моими багами, конечно) как-то получается, что программа не всегда перестартовует предсказуемо. повторяю - пока это наблюдения в сырой программе. возможно, перед выключением я уже там напортил и честное восстановление процессором всего озу уже не поможет...
но все же - есть какие-то подводные камни в описанной инициализации?
Николаев Андрей
22.12.2010, 10:30
Пропадание питания очень просто обходится:
Добавляем модуль статистика в PLC Configuration, и отслеживаем состояние бита power.
f_trig1(power);
if f_trig1.q := 1 then
moy_flag:=...;
end_if
По аналогии - при появлении питания какие то действия с флагами можно выполнить.
Спасибо! Попробую использовать Ваши советы. Еще модуль статистики не трогал.
Powered by vBulletin® Version 4.2.3 Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot