Apr 11

Внимательнее со строками!

Когда-то, очень давно, я не мог понять, почему код, подобный тому, что ниже, возвращал не правильный результат:

function GetText: string;
begin
  Result := Result + '...';
end;

 

procedure TForm1.FormCreate(Sender: TObject);
var
  lStr: string;
  Idx: Integer;
begin
  lStr := 'Text';
  for Idx := 1 to 3 do
    lStr := lStr + '.';
  Label1.Caption := lStr;
  lStr := GetText;
  Label2.Caption := lStr;
end;

 

Как по вашему, что будет в Label2? Если вы думаете, что там будет '...', то вы сильно ошибаетесь, как и я в то время.

В Label2 будет 'Text......' и вот почему: Result в функциях, это не локальная переменная, а параметр-переменная, т.е.

function GetText: string;

идентична

procedure GetText(var Result: string);

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

lStr := GetText(lStr);

Теперь понятно, почему мы получаем существующий результат?

 

P.S.: кстати, данная проблема (точнее, "неявность"), давно известна. Например в книге А.Б. Григорьева на странице 444 она хорошо описана. Жаль у меня не было этой книги тогда, но сейчас есть =). Советую преобрести - там очень большой и полезный раздел по сокетам.


  1. Николай Курков
     Add karma Subtract karma  +2
    Цитировать.

    Спасибо! А я думал, какого хрена у меня всякий мусор в резалте вылезает, приходится обнулять). Теперь все встало на свои места.

    Немного скажу о ресурсе. Ресурс очень хороший, продолжай писать, уверен, он многим понравится и будет популярен в программерских кругах.

    Спасибо!

    1
  2. aktuba
     Add karma Subtract karma  +0
    Цитировать.
    Комментарий автора

    Буду стараться =). Рад что помогло.

    2
  3. idiot inside
     Add karma Subtract karma  --2
    Цитировать.

    Автор, ты или идиот, или плохо читаешь документацию.

    Значение Result в GetText – не инициализировано (не определено), о чем тебе, к сожалению, не говорит компилятор в силу ошибки оного.

    А фактическое поведение – оно фантомно, и может быть изменено в дальнейшем.

    Короче, RTFM

    If the function exits without assigning a value to Result or the function name, then the function’s return value is
    undefined.

    function GetText2: integer;
    begin
    Result := Result + 2;
    end;

    3
  4. aktuba
     Add karma Subtract karma  --1
    Цитировать.
    Комментарий автора

    Зачем грубить то? Ты бы хоть проверил, прежде чем пищать…

    Да, еще кое-что. Если начинаешь что-то доказывать – указывай реальные данные, а не вымышленные. Этим ты хотя бы покажешь, что что-то знаешь, а не переписываешь сообщения с форумов от таких же “знаек”, как тыю

    4
  5. Odysseos
     Add karma Subtract karma  +0
    Цитировать.

    Вообще-то, Result при входе в процедуру/функцию действительно не определена – как и любая другая локальная переменная. И то, что (причем – только для типа String, хотя, надо думать – для динамических массивов должно быть то же самое) она “случайно” в какой-то (каких-то) версии компилятора оказывается определенной в значение той переменной из вызывающей функции, которой потом и присвоится значение Result – именно “случайность” (читай – особенность работы компилятора). И закладываться на такое поведение и в дальнейшем – я бы не стал.

    Собственно – для теста повторите то же самое, но только с Integer’ом, например:


    function GetNum: Integer;
    begin
    Result := Result + 1;
    end;

    procedure TForm1.FormCreate(Sender: TObject);
    var
    n, i: Integer;
    begin
    n := 10;
    for i := 1 to 3 do
    Inc(n);
    Label1.Caption := IntToStr(n);
    n := GetNum();
    Label2.Caption := IntToStr(n);
    end;

    Уверяю Вас – из второго вызова придет “мусор”, а вовсе не 14.

    5
  6. aktuba
     Add karma Subtract karma  +0
    Цитировать.
    Комментарий автора

    Это не в “каких-то” версиях, а именно во всех. Нашел даже описание этого момента.

    6

Поделитесь вашими мыслями

Поддерживаемые теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>