Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2007.01.28;
Скачать: [xml.tar.bz2];

Вниз

Сишные циклы FOR в Паскаль не переводятся?   Найти похожие ветки 

 
for   (2006-12-16 05:52) [0]

У них вообще по-моему это не циклы, а просто несколько присваиваний и условия в круглых скобках с надписью for спереди. То есть как while или until. А настоящих циклов for у них нет. Да?


 
Stexen ©   (2006-12-16 06:31) [1]

Ну а чем тебе сишный for не настоящий???Он наоборот более гибкий чем паскалевский и оч функциональный


 
Stexen2   (2006-12-16 07:02) [2]


> Stexen ©   (16.12.06 06:31) [1]
> Он наоборот более гибкий чем паскалевский


Например он открывает перед тобой возможности завесить цикл. А паскалевский такого не даёт, падла.


 
Думкин ©   (2006-12-16 07:19) [3]

> Stexen ©   (16.12.06 06:31) [1]

Гибкость Сишного цикла FOR полностью доступна чере While. А вот оптимальности Паскалевского FOR в Си нет.
Кстати, в статьях в статье про оптимизацию как раз на эту тему ошибка.


 
for   (2006-12-16 07:24) [4]

Можно ссылку на статью?


 
Думкин ©   (2006-12-16 07:34) [5]


> for   (16.12.06 07:24) [4]

Зайди в статьи на этом сайте - она вроде вторая сейчас там висит.
Но читай критически - статью по косточкам разобрали, - ошибок много.


 
Zeqfreed ©   (2006-12-16 08:46) [6]

Сам недавно занимался таким. Переводится, только циклом while :)

Например такой цикл:
while (p*p < PRIMES_SIZE) {
 for (idx = p*p; idx < PRIMES_SIZE; idx += p)
  primes[idx] = 0;
 while ((!primes[++p]) && (p < PRIMES_SIZE));
}


Я преобразовал в такой:
while (p*p <= High(primes)) do begin
 idx := p*p;
 while (idx <= High(primes)) do begin
  primes[idx] := false;
  Inc(idx, p);
 end;
 
 repeat
  Inc(p);
 until (primes[p]) or (p > High(primes));
end;


Должен признаться, что второй понять проще, но первый выглядит красивее :)


 
ors_archangel ©   (2006-12-16 09:29) [7]


> А паскалевский такого не даёт, падла.

Делфийский for можно заклинить, если использовать не integer, а dword.

>  А вот оптимальности Паскалевского FOR в Си нет.

Оптимальность компиляции в Delphi? Да, действительно, Делф не потянул бы гибкий C-for, он со своим-то еле еле справляется :( А вы видели, какой ужасный код генерит Делфи9 компилятор для for x in … - я уже боюсь расширений языка от Борланда, очень уж они тормознутые получаются :(
Мне в С нравится, что там вместо repeat…until - do…loop,  until всегда требует отрицания, что вообще плохой стиль: "if a" легче понять, чем "if not b", особенно, если высказывания - сложные, вот был бы дополнительно repeat…til - тогда нормально было бы. Борланд хочет, чтобы код выглядел красиво, но не прилагает почти никаких усилий, чтобы можно было писать "красиво" без опаски за скорость, вот, например, начинаешь юзать виртуальные методы, а для них вдруг почему-то smart linking отключается :) (он и не включался просто). FreePascal тоже хреново оптимизирует, но это энтузиастский проект ведь, а не от ведущей корпорации.


 
DiamondShark ©   (2006-12-16 10:36) [8]


> Делфийский for можно заклинить, если использовать не integer,
>  а dword.

Код давай.


> он со своим-то еле еле справляется

Гы, лол, сынку:)


> until всегда требует отрицания

until требует условия завершения.

Типа, матчасть учи, да.


 
Sha ©   (2006-12-16 10:48) [9]

> ors_archangel ©   (16.12.06 09:29) [7]
> Оптимальность компиляции в Delphi?


Оптимальность кода от языка зависит, но не в первую очередь.
В качестве примера - цикл перевода датной строки из формата
"yyyymmdd"T"hh":"nn":"ss" в TDateTime через DOS-представление на Delphi:

 Result:=false;
 if (i=17) and (pBeg[8]="T") and (pBeg[11]=":") and (pBeg[14]=":") then begin;
   i:=0;
   j:=0;
   while true do begin;
     ch:=ord(pBeg[i])-ord("0"); if cardinal(ch)>9 then break;
     if j=1 then ch:=w[j-1]*10+ch;
     w[j]:=ch*10;
     ch:=ord(pBeg[i+1])-ord("0"); if cardinal(ch)>9 then break;
     w[j]:=w[j]+ch;
     if i=15 then begin;
       Result:=TryEncodeDateTime(w[1], w[2], w[3], w[4], w[5], w[6], 0, Value);
       //DateTimeToString(FName,"yyyymmdd"T"hh":"nn":"ss",Value);
       //ShowMessage(FName);
       break;
       end;
     i:=i+1+((i+10) shr 3); //i=0,2,4,6,9,12,15
     j:=j+1;
     end;
   end;


В результирующем коде компилятора нет ни одного умножения,
ни одной лишней загрузки адреса. По-моему, он неплохо справился :)


 
Mystic ©   (2006-12-16 11:54) [10]

Чисто синтаксически у меня большая часть циклов repeat..until False, внутри которых есть Break. С этой точки зрения мне больше по душе конструкция цикла в Ada:


 loop
   Middle := (Left+Right) div 2;
   exit when A[Middle] = Value;
   if A(Middle) < Value then
     Left := Middle + 1
   else
     Right := Middle - 1;
   end if;
   exit whenM/b> Left > Right;
 end loop;


 
Palladin ©   (2006-12-16 11:56) [11]


> ors_archangel ©

парень ты встрял :) надо же столько ерунды нанести...


 
iZEN ©   (2006-12-16 14:41) [12]

Паскалевский for работает с переменными перечислимого типа. Это его ограничивает.
В Си и Java оператор for может работать с любыми значениями, даже с булевыми.


 
wicked ©   (2006-12-16 15:13) [13]

ну так же сказано - for в си-образных = while в паскале... а как вы уж код сложите - ваше дело... :)
спорить, что лучше, что хуже, считаю бессмысленным - это не принципиально, особенно в свете фишечек в обероне 1, отмененных в обероне 2... ;)


 
Eraser ©   (2006-12-16 15:13) [14]

> [12] iZEN ©   (16.12.06 14:41)

а толку с того, через while..do организовать такое же проще простого. см. [3].


 
iZEN ©   (2006-12-16 15:17) [15]


> Eraser ©   (16.12.06 15:13) [14]
>
> > [12] iZEN ©   (16.12.06 14:41)
>
> а толку с того, через while..do организовать такое же проще
> простого. см. [3].

Ну в while нельзя инициализировать ничего. Только ДО, в этом случае такие переменные получают большую область видимости, чем если бы они были инициализированы в теле цикла. А это чревато в многопоточном приложении. :))


 
Eraser ©   (2006-12-16 15:20) [16]

> [15] iZEN ©   (16.12.06 15:17)

а причем тут многопоточные приложения :) ? использовать для циклов не локальные переменные вообще мовитон! вон в C# даже локальные нельзя...


 
iZEN ©   (2006-12-16 15:22) [17]


> Eraser ©   (16.12.06 15:20) [16]
>
> > [15] iZEN ©   (16.12.06 15:17)
>
> а причем тут многопоточные приложения :) ? использовать
> для циклов не локальные переменные вообще мовитон!

Это где такая ересь объясняется?


 
Eraser ©   (2006-12-16 15:27) [18]

> [16] Eraser ©   (16.12.06 15:20)


> вон в C# даже локальные нельзя...

не читать, думал не то что писал ))

> [17] iZEN ©   (16.12.06 15:22)

почему же ересь? компилятор предупреждение выдает даже.


 
Anatoly Podgoretsky ©   (2006-12-16 15:29) [19]

> iZEN  (16.12.2006 14:41:12)  [12]

> В Си и Java оператор for может работать с любыми значениями, даже с булевыми.

for B  := Low(Boolean) to High(Boolean) do;


 
iZEN ©   (2006-12-16 15:31) [20]

Anatoly Podgoretsky ©   (16.12.06 15:29) [19], кстати да, Boolean - тоже перечислимый тип:

var b: Boolean;
begin
 for b := False to True do Button1.Caption := "Done.";
end;


 
vuk ©   (2006-12-16 17:17) [21]

to iZEN ©   (16.12.06 15:22) [17]:
>Это где такая ересь объясняется?
Это не ересь. В pascal for - цикл со счетчиком, в C - цикл с условием. Счетчик, он обычно не в переменной, а в регистре процессора. К тому же если параметр цикла живет в переменной, то возможны разные сторонние влияния на него даже не из того же самого потока.


 
iZEN ©   (2006-12-16 18:33) [22]


> vuk ©   (16.12.06 17:17) [21]
>
> to iZEN ©   (16.12.06 15:22) [17]:
> >Это где такая ересь объясняется?
> Это не ересь. В pascal for - цикл со счетчиком, в C - цикл
> с условием. Счетчик, он обычно не в переменной, а в регистре
> процессора. К тому же если параметр цикла живет в переменной,
>  то возможны разные сторонние влияния на него даже не из
> того же самого потока.
>

То же самое может происходить со счётчиком, я полагаю. Небезопасная конкуррентность с циклом — типичный пример для начинающих работать с потоками. В паскалевском цикле переменная счётчика имеет большую область видимости, так как объявляется перед блоком begin...end — она видима во вне цикла for, её можно использовать ДО, ВО ВРЕМЯ, ПОСЛЕ исполнения цикла совершенно из разных потоков/нитей (к сожалению, синхронизация в Delphi, и тем более в Pascal не развиты и основываются на полностью прикладных мьютексах и самафорах).

В Java (в данном случае я рассматриваю Java, а не Си, хотя для последнего тоже многое справедливо, за исключением многопоточности) невозможно использовать объявленную в нём переменную вне тела цикла. И, пусть поправят, если я не прав, нити, которые начинают выполнение одного и того же блока for, имеют разный контекст по работе с такой переменной — фактически имеют её копию в своём стэке, если блок for не защищён монитором от одновременного выполнения двух и более нитей).
Код:
public class DemoConcurrent {
public static void main(String[] args) {
 Worker w = new Worker();
 Thread t1 = new Thread(w);
 Thread t2 = new Thread(w);
 t1.start();
 t2.start();
}
}

class Worker implements Runnable {
private static int step = 1;
private int j = 0;
public void run() {
 System.out.println("step=" + step++);
 //synchronized (this) {
  for (int i = 0; i < 10; i++) {
   j = j +1;
   System.out.println("" + j + ": i=" + i);
  }
 //}
 System.out.println("step=" + step++);
}
}

Выдаёт:
step=1
step=2
1: i=0
2: i=0
3: i=1
4: i=1
5: i=2
6: i=2
7: i=3
8: i=3
9: i=4
10: i=4
11: i=5
12: i=5
13: i=6
14: i=6
15: i=7
16: i=7
17: i=8
18: i=8
19: i=9
step=3
20: i=9
step=4
Понятно, что переменная i фактически у каждой нити своя? (Каждая нить сохраняет значение переменной i в своём стэке, иначе цикл быстро бы завершился).

После раскомментирования блока synchronized нити будут захватывать монитор объекта w, какая первая получит монитор — та и начнёт выполняться, а вторая нить будет ждать, пока первая не покинет этот блок. Тело цикла будет выполняться сначала одной нитью, а потом другой:
step=1
step=2
1: i=0
2: i=1
3: i=2
4: i=3
5: i=4
6: i=5
7: i=6
8: i=7
9: i=8
10: i=9
11: i=0
12: i=1
13: i=2
14: i=3
15: i=4
16: i=5
17: i=6
18: i=7
19: i=8
20: i=9
step=3
step=4

Переменные j и step объявлены вне тела цикла, тем не менее, операции с ними осуществляется АТОМАРНО, так как они — переменные примитивных типов. Но по первому выводу ясно, что доступ может осуществляться в произвольный момент времени из любой нити. Если бы это были ссылочные переменные (например, на контейнер со счётчиками), то мы имели бы геморрой по поддержке синхронности этих счётчиков.


 
Eraser ©   (2006-12-16 20:30) [23]

> [22] iZEN ©   (16.12.06 18:33)

эт все конечно хорошо, но вот как только на Джаве можно будет писать программы, которые компилятся в полноценный 32/64 разрядный код для win32/64 вот тогда можно будет об этом вообще говорить..


 
Anatoly Podgoretsky ©   (2006-12-16 20:33) [24]

iZEN ©   (16.12.06 18:33) [22]
Локальные переменные в Паскале размещаются на стеке, изначально. Процедуры и функции в Паскале реентерабельны.


 
iZEN ©   (2006-12-16 20:35) [25]


> Eraser ©   (16.12.06 20:30) [23]
>
> > [22] iZEN ©   (16.12.06 18:33)
>
> эт все конечно хорошо, но вот как только на Джаве можно
> будет писать программы, которые компилятся в полноценный
> 32/64 разрядный код для win32/64 вот тогда можно будет об
> этом вообще говорить..

В этом нет необходимости, поскольку быстродействие Java байткода сравнялось с нативным кодом, а перекомпилировать баткод при переходе с 32 битной платформы на 64 битную не нужно.


 
iZEN ©   (2006-12-16 20:44) [26]


> Anatoly Podgoretsky ©   (16.12.06 20:33) [24]
>
> iZEN ©   (16.12.06 18:33) [22]
> Локальные переменные в Паскале размещаются на стеке, изначально.
>  Процедуры и функции в Паскале реентерабельны.

Это я знаю.
vuk ©   (16.12.06 17:17) [21] написал, что значение переменной счётчика цикла в Pascal помещается в регистр процессора. Я хотел показать, что операции над такими переменными не могут быть потокобезопасными. В Java защита производится автоматически (так как копия переменной создаётся на стэке каждой из нитей), невзирая на присутствие/отсутствие synchronized-блока.

Насколько я могу судить, в Pascal/Delphi невозможно атомарное изменение переменной счётчика цикла из разных потоков-нитей без использования мьютекса (функционального аналога явского synchronized-блока), так как переменная фактически принадлежит стэку процедуры, а не нити.


 
Anatoly Podgoretsky ©   (2006-12-16 20:48) [27]

> iZEN  (16.12.2006 20:44:26)  [26]

> Насколько я могу судить, в Pascal/Delphi невозможно атомарное изменение переменной счётчика цикла из разных потоков-нитей без использования мьютекса

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


 
Eraser ©   (2006-12-16 20:50) [28]

> [26] iZEN ©   (16.12.06 20:44)


> Насколько я могу судить, в Pascal/Delphi невозможно атомарное
> изменение переменной счётчика цикла из разных потоков-нитей
> без использования мьютекса (функционального аналога явского
> synchronized-блока), так как переменная фактически принадлежит
> стэку процедуры, а не нити.

можно и с накладными расходами явно меньшими, чем в Джаве.

> написал, что значение переменной счётчика цикла в Pascal
> помещается в регистр процессора. Я хотел показать, что операции
> над такими переменными не могут быть потокобезопасными.
> В Java защита производится автоматически (так как копия
> переменной создаётся на стэке каждой из нитей), невзирая
> на присутствие/отсутствие synchronized-блока.

повторюсь, для циклов надо использовать локальные переменные, в противном случае компилятор выдаст предупреждение. что касается счетчика, так никто не мешает тоже выделить локальную переменную.


 
iZEN ©   (2006-12-16 22:29) [29]


> Anatoly Podgoretsky ©   (16.12.06 20:48) [27]

В принципе, согласен.


> Eraser ©   (16.12.06 20:50) [28]
> повторюсь, для циклов надо использовать локальные переменные,
>  в противном случае компилятор выдаст предупреждение. что
> касается счетчика, так никто не мешает тоже выделить локальную
> переменную.

Приведите пример на Delphi.


 
Eraser ©   (2006-12-16 23:09) [30]

> [29] iZEN ©   (16.12.06 22:29)

насчет глобальной переменной в цикле
var
 Form1: TForm1;
 i: Integer;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
 for i := 0 to 1 do
   beep;
end;

[Pascal Warning] Unit1.pas(28): W1019 For loop control variable must be simple local variable

насчет счетчика в отдельной переменной.
procedure TForm1.FormCreate(Sender: TObject);
var
 i, cnt: Integer;
begin
 cnt := Screen.FormCount;
 for i := 0 to cnt - 1 do
   beep;
end;

хотя со спокойной совестью можно писать и так
procedure TForm1.FormCreate(Sender: TObject);
var
 i: Integer;
begin
 for i := 0 to Screen.FormCount - 1 do
   beep;
end;


 
Anatoly Podgoretsky ©   (2006-12-16 23:13) [31]

> iZEN  (16.12.2006 22:29:29)  [29]

var
  I: Integer;
begin
  ...
end;


 
Stexen ©   (2006-12-17 01:50) [32]


> Думкин ©   (16.12.06 07:19) [3]
> > Stexen ©   (16.12.06 06:31) [1]
>
> Гибкость Сишного цикла FOR полностью доступна чере While.
>  А вот оптимальности Паскалевского FOR в Си нет.
> Кстати, в статьях в статье про оптимизацию как раз на эту
> тему ошибка.

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


 
Eraser ©   (2006-12-17 02:14) [33]

> [32] Stexen ©   (17.12.06 01:50)

уже давно посмотрели :)


 
Mystic ©   (2006-12-17 02:31) [34]

> В данном случае, сишный for с точки зрения кода выглядит
> по приятней...


Тебе более приятно такое?

for(size_t i = N; i--; ) /* Body */ ;


 
Шашка   (2006-12-17 07:13) [35]


> Mystic ©   (17.12.06 02:31) [34]
> Тебе более приятно такое?
> for(size_t i = N; i--; ) /* Body */ ;

Вообще важно то, что цикл с счётчиком - это самостоятельная единица мышления. Которой в Си просто нету. Это как отказываться от умножения, и говорить, что ведь можно получить тот же результат путём сложения.

А ты вроде шашки когда то писал. Может ты знаешь, кто выигрывает в поддавках в начальной позиции ?


 
Anatoly Podgoretsky ©   (2006-12-17 09:22) [36]

> Stexen  (17.12.2006 1:50:32)  [32]

> сишный for с точки зрения кода выглядит по приятней...

Понятие приятности, это понятие красоты и технического определения не имеет. Мне например нравится естественность, вместо искуственности для шаманов.


 
Mystic ©   (2006-12-17 10:35) [37]

По поводу цикла for я имел в виду несколько другое. Конструкция цикла for в C/C++ более гибкая, которая дает код такой же по производительности код. Гибкость проявляется в том, что можно использовать цикл for почти везде, где надо пробежаться по некоторой совокупности данных, будь то список, вектор, проекция и т. д. При этом счетчик цикла не обязательно индекс, а может быть указатель, итератор, ... Но попробуем написать на C аналог цикла:

var
 I: Cardinal;
..............
for I := N-1 downto 0 do /* Something */ ;


Если пойти в лоб, то легко наступить на грабли:

for (size_t i=N-1; i>=0; --i) /* Something */ ;

Это бесконечный цикл ввиду того, что значения типа size_t всегда больше либо равно нуля. Можно вывернуться так, как было показано в [34] (17.12.06 02:31), но лично мне такой вариант не кажется приятным для чтения: столкнувшись с такой конструкцией впервые прийдется потратить некоторое усилие, чтобы разгадать загадку. Получается, что чрезмерная гибкость сишного цикла for дала щелчок по носу.

> Может ты знаешь, кто выигрывает в поддавках в начальной
> позиции ?


Бытует мнение, что поддавки посложнее шашек будут :) Вопрос пока открыт.


 
MBo ©   (2006-12-17 11:14) [38]

>Mystic ©   (17.12.06 10:35) [37]

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

Часто встречается:
for ByteVar := 0 to List.Count - 1 do
при нулевом количестве элементов - облом


 
Sha ©   (2006-12-17 12:36) [39]

> MBo ©   (17.12.06 11:14) [38]

Наверно, поэтому нумерация символов в короткой строке с 1 начинается )


 
Думкин ©   (2006-12-17 14:09) [40]


> Stexen ©   (17.12.06 01:50) [32]

Все что может Сишный фор, я легко достигаю вайлом. И проблем ни в чем не вижу. А фор в Паскале - тут уже много напсали - условие окончаний считаетися единожды.
Т.е.

for(i=1;i<=length(c);i++){}

for i:=1 to length(c) do


Разные вещи. В паскале подобное достигается  

i := 1;
while i <= length(c) do begin
....
inc(i)
end;


Либо repeat...until;



Страницы: 1 2 3 4 5 6 вся ветка

Форум: "Прочее";
Текущий архив: 2007.01.28;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.58 MB
Время: 0.048 c
11-1146668762
AndreyRus
2006-05-03 19:06
2007.01.28
GRAPHCTL_XPSTYLES vs Manifest


1-1164894605
salexn
2006-11-30 16:50
2007.01.28
Как определить установлена ли нужная версия MSXML?


6-1156410841
Zaborostroitel
2006-08-24 13:14
2007.01.28
Перехват адресной строки IE


15-1168349734
@!!ex
2007-01-09 16:35
2007.01.28
Углы Эйлера


15-1168167674
ogi123
2007-01-07 14:01
2007.01.28
Python





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский