Пробую осмыслить заковыристый стиль уважаемого Учителя. Начнем с простого:
Сообщение от
Валенок
2. Если отбросить словесную шелуху, то использование uint или word – по барабану, при условии что вы четко понимаете как они работают на уровне битов.
Ну непонятна мне фраза "если вы четко понимаете". Насколько четко?
На уровне размещения в памяти побайтно - трудно вообразить, что для uint и word используется разные правила. Значит, думаем. что старший байт uint и старший байт word будут лежать одинаково. Так?
Побитно - дык, в байте уж никак не развернут наоборот.
Что еще нужно понимать, чтобы забыть вообще про существование типа uint?
Вопрос даже не в практической плоскости, а в понимании "странности" стандарта.
Теперь к главному.
Сообщение от
Валенок
для работы с заранее неопределенным типом можно использовать dword, по этому "просто поинтер" не нужен.
Похоже, что есть разница, что использовать. Я провел эксперименты, запутался безнадежно, потом сузил поле до 2-х типов: WORD и DWORD. И что получилось.
Готовим несколько переменных типа WORD и DWORD, причем из W и DW будем только черпать инфо, их не изменяем. А для измены есть переменные с цифрами 1...4.
Также есть по 2 указателя, одна пара будет использоваться для указание на источник данных, другая - на приемник.
Код:
VAR
DW: DWORD := 16#10104;
DW1: DWORD;
DW2: DWORD;
DW3: DWORD;
DW4: DWORD;
pDWsour: POINTER TO DWORD;
pDWdest: POINTER TO DWORD;
W: WORD := 16#102;
W1: WORD;
W2: WORD;
W3: WORD;
W4: WORD;
pWsour: POINTER TO WORD;
pWdest: POINTER TO WORD;
END_VAR
В программе 4 шага. В каждом из них рассматриваетм передачу данных, указываемых пойнтерами, в ячейки, адресуемые тоже через указатели. При этом каждый из шагов отличается тем, что присвоение указателям значений (адресов ячеек) производтся с "вывихами":
Код:
pDWsour := ADR(DW); (* Source is right *)
pWsour := ADR(W);
pDWdest := ADR(DW1); (* Destin is right *)
pWdest := ADR(W1);
pDWdest^ := pDWsour^ +1; (* DW <= DW *)
pWdest^ := pWsour^ +1; (* W <= W *)
pDWsour := ADR(W); (* Source is wrong *)
pWsour := ADR(DW);
pDWdest := ADR(DW2); (* Destin is right *)
pWdest := ADR(W2);
pDWdest^ := pDWsour^ +1; (* DW <= W, fetch throu pDW *)
pWdest^ := pWsour^ +1; (* W <= DW, fetch throu pW *)
pDWsour := ADR(DW); (* Source is right *)
pWsour := ADR(W);
pWdest := ADR(DW3); (* Destin is wrong *)
pDWdest := ADR(W3);
pDWdest^ := pDWsour^ +1; (* W <= DW, written throu pDW *)
pWdest^ := pWsour^ +1; (* DW <= W, written throu pW *)
pDWsour := ADR(W); (* Source is wrong *)
pWsour := ADR(DW);
pWdest := ADR(DW4); (* Destin is wrong *)
pDWdest := ADR(W4);
pDWdest^ := pDWsour^ +1; (* W <= W throu pDW *)
pWdest^ := pWsour^ +1; (* DW <= DW throu pW *)
Результаты таковы. Во-первых, компилятор не ругается. Хотя, когда я пробовал приемник данных указывать явно - требовал иногда преобразования типов.
А дальше вот что. При правильном использовании пойнтеров все хорошо, но это ясно. В остальных случаях некоторые присвоения правильны, некоторые нет. Более того, выполнение последнего оператора (передача двойного слова через 2 пойнтера на слово) - прерывает исполнение программы
Доступ по несуществующему адресу. ПЛК остановлен
(Слава Богу, что мы не управляли котельней!)
Грустный вывод. Хоть компилятор и пропустит, но жизнь поправит. Причем, уважаемый Учитель, хочу заметить, что даже при использовании указателя высшего типа на (шаге 2)
pDWdest^ := pDWsour^ +1; (* DW <= W, fetch throu pDW *)
результат неверен
Т.е., использование DWORD при выборке из переменной типа WORD "прихватывает" еще несколько байт и пихает их в приемник (в нашем случае это приемник типа DWORD, поэтому мы и увидели всеь ужас прихватки).
Не знаю, наскольок мои путанные мысли что-то продвинули, но теперь думаю, что придется все переменные, на которые буду указывать DWORD-пойнтером, искусственно повышать до типа DWORD. А там еще и переменные TIME есть... Пойду удавлюсь.