Как увеличить значение цикла FOR в операторе цикла FOR?

Я хочу знать, как увеличить значение в операторе цикла FOR.

Это мой код

function Check(var MemoryData:Array of byte;MemorySignature:Array of byte;Position:integer):boolean;
var i:byte;
begin
 for i := 0 to Length(MemorySignature) - 1 do
 begin
  while(MemorySignature[i] = $FF) do inc(i); //<< ERROR <<
  if(memorydata[i + position] <> MemorySignature[i]) then Result:=false;
 end;
 Result := True;
end;

Ошибка: E2081 Присвоение переменной FOR-Loop 'i'.

Я пытаюсь перевести старый код из C # в Delphi, но я не могу увеличить "i". Увеличение & i; это не единственный путь, но я хочу знать, где проблема.

Ответы на вопрос(6)

Решение Вопроса

Конечно, остальные (в целом) правильны. То, что не было сказано, это то, что "я"; в вашей петлеdoesn't существовать. Delphi использует для этого регистр процессора. Вот почему вы не можете изменить его, и именно поэтому вы должны использовать «для». цикл (не "пока"), потому что "для"; это намного быстрее. Вот ваш код изменен (не проверен, но я думаю, что вы поняли идею) - также imho у вас было несколько ошибок - также исправил их:

function Check(var MemoryData:Array of byte;MemorySignature:Array of byte;Position:integer):boolean;
var i:byte;
begin
 Result := True; //moved at top. Your function always returned 'True'. This is what you wanted?
 for i := 0 to Length(MemorySignature) - 1 do //are you sure??? Perhaps you want High(MemorySignature) here... 
 begin
  if MemorySignature[i] <> $FF then //speedup - '<>' evaluates faster than '='
  begin
   Result:=memorydata[i + position] <> MemorySignature[i]; //speedup.
   if not Result then 
     Break; //added this! - speedup. We already know the result. So, no need to scan till end.
  end;
 end;
end;

... также MemorySignature должно иметь «const» или 'var'. Иначе, как сейчас, массив копируется. Что означает замедление при каждом вызове «Check». Наличие «var» все происходит намного быстрее с неизменным кодом, потому что AFAIS MemorySignature не изменилась.

НТН

 10 июл. 2009 г., 12:13
& APOS; & APOS конструкции; Это еще один вариант, который сочетает в себе преимущества двух выше. Это означает, что параметр перенесенby reference (следовательно, вызов очень быстрый), но параметр остается неизменным "снаружи". Это достигаетсяprohibiting «предварительное изменение»; компилятором во время компиляции. IOW этот параметрconstant (отсюда и название: «const») во всем теле функции. Пример: функция MyFunc (const a: строка); начать; а: = & APOS; Foo & APOS ;; конец; - когда вы пытаетесь скомпилировать это, компилятор выдаст ошибку вa:='Foo';  HTH (извините за мои большие комментарии :-))
 10 июл. 2009 г., 15:41
Выделение "я" регистр не означает, что он исчезает, он просто означает, что для него нет адреса. Я не понимаю акцента на оптимизации компилятора в ответах здесь. Оптимизация происходит потому, что язык запрещает определенное поведение, а не наоборот.
 10 июл. 2009 г., 12:09
Есть несколько способов передачи параметров. Значение по умолчанию - по значению: s: = 'Foo & apos ;; MyFunc (ы); Написать (s); напишет «Foo»; независимо от того, что происходит внутри MyFunc, и это потому, что & s; это получитьcopied внутри функции (для защиты «внешних элементов» от изменений, происходящих внутри MyFunc) и если «s»; большой (много КБ), то это может быть дорого. Добавление «var» там означает, чтоonly указатель на «s»; (ссылка на 's') пропускается, что намного быстрее (всего несколько байтов), но это означает, что любые изменения, которые происходят внутри вашей функции, будут "видимыми". вне.
 10 июл. 2009 г., 11:58
& APOS; Перерыв & APOS; означает «Out of current LOOP». (для т. д.) в то время как «выход»; означает «Из текущего БЛОКА КОДА» quot; (процедура / функция и т. д.). В нашем конкретном случае, да,is то же самое, но (imho) - хороший навык кодирования для завершения функции на конечном «конце». Конечно, это общее правило, а не догма. Предположим, что кто-то другой берет код, и он решает, что после каждой проверки он должен стереть (IOW fill с # $ 00) MemorySignature, независимо от результата функции. Инстинктивно он "добавит" для " петля в конце. Если есть «Выход»; в середине, то этот кодsometimes пропущен
 30 июл. 2009 г., 05:22
for абсолютно не гарантирует, что индексная переменная будет помещена в регистр (это должно быть очевидно хотя бы потому, что вы можете четко написать достаточно много вложенныхfor-переключается, что не хватает регистров для помещения переменных!). Более того, другие переменные могут (и являются) также вноситься оптимизаторами в регистры. Наконец, помещение переменной в регистр не влияет на ее изменчивость - регистры, очевидно, могут быть назначены точно так же, как и ячейки памяти. В целом, ужасное объяснение, которое может быть как фактически неверным, так и отвлекающим от реальной проблемы.

Проблема в том, что компилятор взял исходный код цикла FOR и предположил, что знает, что происходит, и, таким образом, он может оптимизировать код, выводя конкретные инструкции процессора, которые выполняются быстрее всего, с этими допущениями.

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

Вместо этого вам нужно просто иметь отдельную переменную, которую вы фактически используете, и использовать только индексную переменную цикла FOR, чтобы отслеживать, сколько итераций вы выполнили в настоящее время.

Например, типичной оптимизацией может быть написание инструкций ЦП, которые прекратят итерацию, когда регистр индекса упадет до нуля, переписав цикл таким образом, что он будет вести внутренний отсчет, а не вверх, и если вы начнете возиться с переменная, он не мог переписать код таким образом.

 09 июл. 2009 г., 20:04
Оптимизатору несложно увидеть, назначена ли переменная управления циклом в теле цикла. Похоже, что более вероятное назначение не позволяет легче понимать вещи - ради читателя-человека.
 09 июл. 2009 г., 20:06
@ Майкл: А также потому, что оригинальный Паскаль работал именно так.

Согласно Майку Саттону, вам нужен цикл while, а не цикл for.

function Check(var MemoryData: Array of byte; 
  MemorySignature: Array of byte; Position: Integer):Boolean;
var 
  i:byte;
begin
 Result := True;
 i := 0;
 while i < Length(MemorySignature) do
 begin
   while(MemorySignature[i] = $FF) do 
     Inc(i); 
   if(MemoryData[i + position] <> MemorySignature[i]) then 
     Result := False;
   Inc(i);
 end;
end;

Delphi-реализация "для" оптимизирован, но в результате он менее гибок, чем стиль C

В дополнение к тому, что написал Лассе,assigning to a loop variable is generally considered a code smell, Это затрудняет чтение кода (если вы хотите преждевременно выйти из цикла, вы можете выразить это намного яснее, используя break / continue), и это часто делаетсяby accident, вызывая все виды неприятных побочных эффектов. Таким образом, вместо того, чтобы прыгать через обручи, чтобы компилятор не выполнял оптимизацию fu в любом цикле, где затрагивается переменная цикла, Borland (теперь CodeGear) укусил пулю и сделал присвоение переменной цикла недопустимым.

Если вы действительно хотите возиться с индексами цикла вручную, подумайте об использовании цикла while.

 10 июл. 2009 г., 06:10
+1 Пока идет цикл с хорошо названной логической тестовой переменной. Тогда вы можете иметь счетчик, аналогичный исходному, но логическое тестовое значение включает в себя как пороговый тест для этого значения, так и одно или несколько других условий. Контроль цикла должен быть кристально чистым.

Если вам нужно изменить счетчик цикла внутри цикла, попробуйте использовать цикл while.

Кстати, вам нужен ваш     Результат: = True строка, которая будет первой строкой функции для правильной работы. Как это, он всегда будет возвращать True.

в этом случае вы можете просто сделать «продолжить»; вместо inc (i)

 09 июл. 2009 г., 20:02
Чтобы уточнить далее, i увеличивается автоматически (часть конструкции for) в конце каждой итерации цикла for.

Ваш ответ на вопрос