Добрый день.
Как в CDS осуществить проверку указателя на Null?
Вид для печати
Добрый день.
Как в CDS осуществить проверку указателя на Null?
Проверяйте равенство указателя с нулем.
Вообще-то я так никогда не делаю, не знаю где это может понадобиться. :)
plist ->(pnext->)->(pnext->)->(pnext=nil)
простейший односвязный список из 3х объектов.
PS
Прогон неких фб из списка
обмен/архивация/события/...Код:pcurrent := plist;
while pcurrent <> nil do
pcurrent^(pnext => pcurrent);
end_while
В данном случае - искусственный т.к. является принудительно устанавливаемым при инициализации объекта в выделенном куске памяти.
Но вот при выделении самого участка памяти для объекта (из кучи) - может вернутся и случайный что будет является всего лишь признаком невозможности расширении списка а не перезагрузки ПЛК.
Любой проект является как бы (С) а возможные области применения я показал. Именно там я их и применяю.
Например архивация.
Объекты генерят события в динамический список.
При ненаступлении некоторых критических событий часть событий самоуничтожается (чтоб не плодить избыточную инфу)
Архиватор формирует из нужных событий буфер
Буфер при превышении 512 байт сливает окно (512 байт) в архив флеша
Рез-т : Имеем архив важных событий с подробной ситуацией перед наступлением аварий.
как, выделяя динамически память, я указываю какой тип данных будет и ОС вернет мне требуемый кусок памяти либо ноль что означает что не удалось найти подходящий объем памяти для объекта, т.ею случайности быть не может. Другими словами если проверять что возвращает функция(а этого требует и документация) в дальнейшем проверять и на несуществующий экземпляр не придется
Ну так и есть - случайное образование nil при вызове выделителя памяти
Используемая инициализация объекта с полем pnext (выше) - принудительная установка
Но для проверяющего список - появление nil в поле pnext текущего объекта опять же - случайное. Проверяющий не знает заранее кол-во элементов в списке. Ему это вообще побоку. Он вообще в библиотеке. Вводить дополнительную сущность ?
PS
Изв. за перерыв. Шашлык не ждет
что есть список? в МЭК нет такого оператора, если это что то своё, то стоит позаботиться то методе size() чтоб проверяющий мог знать количество элементов. Если это массив строк, то на место удалённых обычно смещают последующие элементы, не могу я представить появление null-об'ектов в КДС
null сам по себе традиционно не является и не относится к типам данным. Это самостоятельная лексическая единица, обозначающая неинициализированный указатель. Без неё можно жить. C++ обходился и обходится без поддержки null со стороны компилятора, но в C++11 (2011) литерал nullptr был введён на замену устоявшейся нулевой константе NULL, вместо которой можно писать просто 0.Цитата:
типа данных null
Список есть совокупность смежно-связанных элементов. Следует различать массив и список (массив есть совокупность смежно расположенных в памяти элементов). В отличие от массива, для функционирования списка не требуется определение его размера, но при этом отсутствует произвольный доступ за константаное время по индексу элемента (как следствие неопределённого размера и расположения элементов в памяти — требуется обход с попутным вычислением индекса). Возможны смешанные реализации.Цитата:
что есть список?
Практика программирования такова, что списки чаще используют там, где не требуется знать количество элементов. Вы начинаете обход списка с заранее известного элемента (чаще с головы или хвоста) и продолжаете до тех пор, пока вам не надоест или не попадётся пустой указатель (0, NULL, NIL, nullptr и т.д.) на следующий элемент, что и будет означать конец списка во взятом вами направлении.Цитата:
чтоб проверяющий мог знать количество элементов
Егор замечательно все сказал. Чисто добавить :
Ключевое слово - константа. Именованные константы повышают читабельность и переносимость.Цитата:
введён на замену устоявшейся нулевой константе NULL, вместо которой можно писать просто 0..
Хоть и везде несуществующий указатель это 0, но писать 0 или NULL - это из серии выбирать между 0/1 и TRUE/FALSE (в КДС). Без разницы, но лично я всегда пишу TRUE/FALSE.
тут точно все говорят про мэк, в яве я пользуюсь проверкой на null, на здесь у меня в окне объявлений компилятор не допустит непринициализированный объект.
что касается списков, я знаю обобщенно два вида списков, нумерованный (enum) и list, первый насколько понимаю встречается в кдс и там нам известно в каких случаях будет null
по поводу нуля, указатель вернувший ноль, мне кажется совсем не то, что указатель на тип null, это я про то как звучит вопрос темы
зы кого то вот шашлыки ждут, а меня Уфа, т.ч. проверить все вышесказанное в кдс не смогу)
про тип null Егор уже сказал.
автор темы, предполагаю, имел ввиду как кто проверяет указатель на предмет того а указывает ли он.
а что Егор сказал такого про null, применительно в КДС, например указатель на реал, ткните его в любую точку памяти, когда это он вернет null?
Не вернет, а сам есть null
var
p : pointer to real;
Вот напишу я вам библиотеку, в которой одна из функций будет возвращать указатель (адрес) на буфер, и скажу, что в случае неудачи эта функция возвращает NULL (0). На этапе загрузки вы с этим ничего сделать не сможете. Вам придётся в своей программе проверять значение, возвращённое моей функцией, чтобы оно не оказалось равным нулю. Буквально IF ptr <> 0 THEN... Так?
В Жаве в аналогичной ситуации вы бы написали if (xyz != null) и никак иначе, потому что там модель ссылочная, адреса скрыты от программиста, ссылки в чистом виде не являются для программиста числами, и следовательно, сравнивать их с нулём нельзя — из-за чего и введена литера null (не является типом и не имеет своего типа; это своеобразный нолик для проверки и инициализации ссылок любого типа). UPD: спеки на Жаву в п. 4.1 говорят, что null таки имеет свой тип, но этот тип не имеет имени. In practice, the programmer can ignore the null type and just pretend that <code class="literal" style="color: rgb(0, 0, 0); font-size: 10.1999998092651px; font-style: italic; line-height: 16.7999992370605px;">null</code> is merely a special literal that can be of any reference type.
Но некоторые идут из страны весёлых языков Си/Си++. Особенно Си++. Ссылочная система там гарантирует, что объект будет валидным — null как в Жаве не требуется, и его нет. Но помимо неё есть ещё указательная система, и адреса под указателями имеют неявно числовой тип и могут быть какими угодно. До 2011 года полученные извне адреса сравнивали с нулём. Но для читаемости и чтобы не путать указатели с числами вместо нуля часто писали NULL (глобально определённая библиотечная константа, которая на самых первых этапах компиляции подменялась нулём). По той же причине люди пишут TRUE/FALSE вместо 0/1, как Валенок выше уже упомянул. А в 2011 стандартом на замену этому колхозу был введён литерал nullptr, который уже поддерживается на уровне компилятора как null в Жаве, но для указателей, а не для ссылок.
И вот SKV спрашивал, есть ли что-то вроде NULL/nullptr из мира Си++ (или ещё откуда). Ответ отрицательный: указатели придётся сравнивать с нулём или определить для себя константу с именем NULL.
да не буду я пользоваться функцией, которая возвращает всё что угодно, скорее всего в таком случае перейду на яву, если это не решается в плк. И кста в ней , не обязательно буду возвращать null, лучше выбросить исключение. И еще если я объекту присвою null то он отправится в мусор и должен освободить ресурсы, в плк присвоив указателю ноль, он всёравно будет занимать двойное слово, а объект на который ссылался останется в памяти и надеюсь тоже сотрется со временем, а не останется занимать ресурсы
Не всё что угодно, а нуль при неуспешном завершении. Это слишком распространённый приём, чтобы взять и махнуть на него рукой.
Существование и инициализированность указателя никак не влияют на время жизни объектов. Сборка мусора, когда она вообще есть, работает подсчётом ссылок. Указатели — не ссылки, а ссылки — не указатели.
я предпочитаю создать буфер, а в функцию передать указатель для его обработки
Тогда код функции будет иметь проверку Вашего указателя на 0
Вот для чего я собираюсь использовать проверку на null.
FUNCTION_BLOCK DispatcherModbus
VAR_INPUT
pModule : ARRAY[1..247] OF POINTER TO ModuleBase;
END_VAR
pModule - массив указателей на модули.
При первом вызове DispatcherModbus, я должен передать ссылки на все модули, которые у меня есть в системе.
Остальные остаются равными null. Затем в диспетчере я проверяю, есть ли модуль проверкой на null.
Так что проверка нужна.
Спасибо за совет использовать константу вместо 0, действительно, красивее.
я не отрицаю что проверки понадобятся, но могу использовать sizeof, а в функции через цикл прогнать, пускай даже нулевое количество циклов, только бы не по Вашему было :)
только всё равно не понимаю, как инициализированный буфер может не получить указатель, который Вы заставляете меня проверять, а уж инициализировать массив NULL значениями, эх, я так не умею
как компромисс - можно такЦитата:
только бы не по Вашему
if p < 1 then
а вотЦитата:
а уж инициализировать массив NULL значениями, эх, я так не умею
Цитата:
FUNCTION_BLOCK DispatcherModbus
VAR_INPUT
pModule : ARRAY[1..247] OF POINTER TO ModuleBase;
END_VAR
у меня так рука не поднимется, я бы написал: pModule : ARRAY[1..247] OF DWORD := 0(247);
и то чтоб проверить
а на самом деле так проекты не пишутся, через бибку у меня вообще не встанет вопросов с адресацией, ООП в КДС2 не существует, поэтому ModuleBase это частный случай и универсальности от него ноль, полюбому писать реализацию каждый раз свою и под каждое устройство другого типа, про то чтобы держать в конфигураторе слейвы более 32 штук у меня сразу вопрос а тот ли контроллер выбрал человек
Если написать так: pModule : ARRAY[1..247] OF DWORD := 0(247);, то у Вас будет массив DWORD и как Вы будете обращаться к полям структуры ModuleBase не понятно. А я это делаю вот так:
if pModule[1]^.ReqForPooling then ....
Структура ModuleBase содержит поля, которые должны быть у любого модуля. Эти поля отвечают за организацию опроса. А вот остальная реализация модуля у каждого типа модулей, действительно, своя. Один обращается к регистрам хранения, другой к входным регистрам. Один читает 2 регистра, другой 8 и т.д. и т.п.
Одним словом ModuleBase - это базовый тип всех модулей. Конечно, организовать классическое ООП не получится, но писать в стиле приближенным к нему можно.
Указатель-то размерности dword, но если вы объявите так как предлагаете, то не сможете работать с полями ModuleBase.
Вы фактически передаете тоже указатель на Base. Только зачем-то его объявляете, как dword?
первое что в голову приходит, писать меньше :)
с двордом у меня нет необходимости прописывать указатель на какой объект я собираюсь обрабатывать