Что происходит, когда AnsiString брошен в PAnsiString?

Если я вас правильно понимаю, вам нужно будет использовать REPLACE в условии соединения. Кроме того, поля с одинаковыми именами должны иметь префикс:

SELECT 
    PRODUCTION_ALL.* 
    CAST (PLTReports.ENDDATE AS DATETIME) AS ENDDATE 
FROM PLTReports 
INNER JOIN PRODUCTION_ALL ON PRODUCTION_ALL.ITEMID = REPLACE (PLTReports.ITEMID,'CV','PH')
5
задан Cesar Romero 14 February 2009 в 20:04
поделиться

2 ответа

Хорошая загадка, но у меня есть решение:

  • P2 и P3 являются адресом указателя на буфер
  • P1 и P4 являются адресом буфера
  • P5 является первым элементом в буфере

Я добавил комментарий в коде:

var
  Buffer: AnsiString;
  P1: Pointer;
  P2: Pointer;
  P3: Pointer;
  P4: Pointer;
  P5: Pointer;
begin
  P1:= PAnsiString(Buffer); 
  (* A cast from AnsiString to PAnsiString has no real meaning 
     because both are a pointer to a block of characters ()
  P2:= Addr(Buffer);
  P3:= @Buffer;
  (* Both Addr and @ give the address of a variable. The variable Buffer is 
     a pointer so we get the address of the pointer, not the value of the 
     pointer. *)
  P4:= Pointer(Buffer);
  (* See the remark on P1. Due to the cast both give the same result. *)
  P5:= PChar(Buffer[1]);
  (* This looks like a pointer to the first element. But the cast changes 
     it into the character. *)
  WriteLn('P1: ' + IntToStr(Integer(P1)));
  WriteLn('P2: ' + IntToStr(Integer(P2)));
  WriteLn('P3: ' + IntToStr(Integer(P3)));
  WriteLn('P4: ' + IntToStr(Integer(P4)));
  WriteLn('P5: ' + IntToStr(Integer(P5)));
end;
7
ответ дан 18 December 2019 в 07:11
поделиться

AnsiString реализован как указатель. AnsiString переменная содержит только адрес. Адрес что имеет первый характер в строке, или nil если строка пуста.

A PAnsiString указатель на AnsiString переменная. Это - указатель на указатель на первый символ строки. Когда Вы говорите PAnsiString(Buffer), Вы говорите компилятору рассматривать указатель в Buffer как будто это был указатель на AnsiString вместо указателя на символьные данные. Адрес 5006500 является местоположением первого символа строки, C.

У Вас есть запись в памяти, которая представляет строку:

                +-----------+
                | $ffffffff | -1 reference count (4 bytes)
                +-----------+
Buffer:         | $00000001 | length (4 bytes)
+---------+     +-----------+
| 5006500 | --> |       'C' | first character (1 byte)
+---------+     +-----------+
                |        #0 | null terminator (1 byte)
                +-----------+

Buffer содержит адрес байта с C в нем. Вы преобразовываете тип этого, чтобы иметь тип PAnsiString вместо AnsiString. Вы сказали компилятору, что у Вас было это расположение:

                                  +-----------+
                                  |       ... |
                                  +-----------+
Buffer:                           |       ... |
+---------+     +-----------+     +-----------+
| 5006500 | --> | $00000043 | --> |   garbage | first character
+---------+     +-----------+     +-----------+
                                  |       ... |
                                  +-----------+

Когда я рассуждаю об указателях, я рисую схемы точно так же, как это. Если Вы не сохраняете небольшого количества бумаги рядом с Вами на Вашем столе, Вы вредите себе.

15
ответ дан 18 December 2019 в 07:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: