-
Какой результат у вас? 20 или 30?
var t1,t2:Integer; function foo(var a,b:Integer):Integer; begin a:=10; b:=20; a:=a+10; b:=a; Result:=b; end; begin t2:=foo(t1,t1); WriteLn(t2); end.
ПС. Интересуют разные компиляторы и их версии в том числе питон и Си диез.
-
> в том числе питон и Си диез.
Ошибка компиляции.
-
С какой радости может быть 20?
-
Тоже самое, если сделать
var
t1: Integer;
t2: Integer absolute t1;
-
У меня 30. Delphi XE6 Prof. Win64.
-
Поддерживаю, из-за var будет 30, а как может быть по другому? Если по значению, то будет 20.
Вроде очевидно, что во всех языках. Если там поддерживается передача по ссылке, то будет 30. Если не поддерживается, то пример транслировать нельзя и скорее всего будет 20. В чем смысл вопроса?
-
В том что var это не должен быть передачью по ссылке. Это должно быть передача по значению с возвратом результата.
-
> [6] Pavia © (01.06.17 06:15) > Это должно быть передача по значению с возвратом результата
Это как?
-
Всмысле как? То как описывал Вирт. Он специально отказался от передачи по ссылке и по указателю. Введя понятия var и const. И мне обсолютно не прнятно почему Delphi не следует стандарту.
-
> Pavia © (01.06.17 06:15) [6] > var это не должен быть передачью по ссылке. Это должно быть > передача по значению с возвратом результата.
Допустим, что так. Но тогда сразу возникают вопросы: - по какому адресу надо этот результат разместить? - как вызывающая сторона узнает этот адрес?
-
> [8] Pavia © (01.06.17 07:36) > То как описывал Вирт.
Напомни точную цитату, я наверное и не читал Вирта, но как уже сказал ЮЗ, фактически компилятор должен генерировать 2 параметра - один для значения, второй для возврата, что нарушает саму идею о возможности модификации передаваемого параметра в вызываемой функции.
-
> Pavia © (01.06.17 07:36) [8] > ... Вирт ... специально отказался от передачи по ссылке и по указателю. > Введя понятия var и const.
Насколько помню, при передаче параметров в Паскале Вирт ни от чего не отказывался и атрибут const для параметров не вводил. Этот атрибут появился только в Delphi, причем даже и не в ранних версиях. А у Вирта - как у Вирта, все просто и четко:
- есть var - передается адрес; - нет var - передается значение.
-
> Допустим, что так. Но тогда сразу возникают вопросы:- по > какому адресу надо этот результат разместить?- как вызывающая > сторона узнает этот адрес?
Для результата функции с типом record они это сделали. Если функция возвращает запись. То в стеке формируется переменная под эту запись. В параметры функции добавляется ещё одно поле с указателем на это переменную. По выходу из функции вызывающая сторона копирует данные из временной переменной в ту которой должна присвоить по коду.
Для var можно поступить так же. Для оптимизации всёже будем использовать ссылки. Если в функцию передаются разные переменные они передаются по ссылке. Если одна переменная передаётся 2 и более раз. Для них заводятся локальные переменные по числу дублей минус оригинал. Размножаем исходную переменную. И вызываем функцию как обычно. Только вначале теневые копии, а в конце оригинальная переменная. Тогда выходные данные сразу попадут в оригинальную переменную без лишнего копирования. На изменения будет влиять крайний правый параметр.
Можно и без ссылок. Значения записываются во стековый фрейм. Фрейм имеет размеры по размер всех параметров. Затем вызываем функция. По выходу из фрейма обратно пересылаются в нужные переменные. При таком подходи получается что за освобождение и выделение памяти отвечает вызывающая сторона.
Важно, что в результате алгоритм-функции будет предсказуем. Изменение b не будет приводить к изменению переменной a.
Насколько слышал в Питоне как-то это же реализовано. По крайней мере переменные не ведут себя подобно запутанным-фотонам.
-
> Если одна переменная передаётся 2 и более раз. Для них заводятся > локальные переменные по числу дублей минус оригинал. Размножаем > исходную переменную. И вызываем функцию как обычно.
Ну допустим. А что тогда должен вывести на консоль такой код: var t1:Integer;
function foo(var a,b:Integer):Integer; begin a:=10; b:=20; end;
begin foo(t1,t1); WriteLn(t1); end.
-
> переменные не ведут себя подобно запутанным-фотонам
Есть var - передается адрес; Нет var - передается значение.
Где тут путаница?
-
> Kerk © (01.06.17 09:17) [13]
> что тогда должен вывести на консоль такой код
Такой код должен вывести: "Аффтар, убей сибя ап стену". :o)
-
Юрий Зотов © (01.06.17 09:53) [15]
"Еще не хотелось бы видеть открытого коверканья русского языка, использования уличного сленга. Это конечно не наказуемо, но помните, что Ваши слова будут читать люди, которые с ними могут быть незнакомы, или они им просто неприятны. "
Мне - просто неприятно
-
> Kerk © (01.06.17 09:17) [13]
Я уже написал. Крайнее правое (var a,b:Integer). То бишь значение b. Это логичнее, чем передавать по ссылке. И наводить путаницу.
-
> Pavia © (01.06.17 13:25) [17] > > > > Kerk © (01.06.17 09:17) [13] > > Я уже написал. Крайнее правое (var a,b:Integer). То бишь > значение b. > Это логичнее, чем передавать по ссылке. И наводить путаницу.
Ну вот вообще ни разу не логичнее
-
Ну 30 должно быть, очевидно же? С этими var'ами много чудес. Особенно с неявными. Ниже код. Без теста, кто скажет, Button1 и Button2 полностью ли идентичны?
type
TPerson = record
FIO: String;
Age: Integer;
end;
function InitPerson(const FIO: String; Age: Integer): TPerson;
begin
FillChar(Result, SizeOf(Result), 0);
Result.FIO := FIO;
Result.Age := Age;
end;
procedure TForm_Tests.Button1Click(Sender: TObject);
var
Person: TPerson;
Persons: array of TPerson;
begin
SetLength(Persons, 3);
Person := InitPerson('И.И. Иванов', 40);
Persons[0] := Person;
Person := InitPerson('И.И. Сидоров', 42);
Persons[1] := Person;
Person := InitPerson('И.И. Петров', 45);
Persons[2] := Person;
end;
procedure TForm_Tests.Button2Click(Sender: TObject);
var
Persons: array of TPerson;
begin
SetLength(Persons, 3);
Persons[0] := InitPerson('И.И. Иванов', 40);
Persons[1] := InitPerson('И.И. Сидоров', 42);
Persons[2] := InitPerson('И.И. Петров', 45);
end;
|