Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.12.09;
Скачать: CL | DM;

Вниз

Передача строки в параметр PChar   Найти похожие ветки 

 
KSergey ©   (2007-11-12 08:47) [0]

Имеем процедуру:

procedure SomeProc(AStr: PChar);

Вызываем ее так:

  SomeProc("SomeString");

Компиялтор не ругается и вроде даже все работает (т.е. в ыункция приезжает то, что и ожидалось и в строке внутри процедуры завершающий нуль присутствует). Но по косвенному признаку вдруг закралось подозрение: все ли тут хорошо?

Что собственно беспокоит:
1) Действительно ли корректно передавать строку в параметр PChar без явного преобразования PChar("SomeString")? Я понимаю, что это предбрпзование отчасти фейковое и вроде явного вызова какой-либо процедуры не происходит, но все же?
2) Всегда ли строки в дельфи хранятся с завершающим нулевым символом?

Я понимаю, что "практика - критерий истины", но может кто подскажет место, где эти моменты явно написаны? Куски кода, формирующего строки, например - вполне подойдут.


 
Anatoly Podgoretsky ©   (2007-11-12 09:02) [1]

> KSergey  (12.11.2007 08:47:00)  [0]

1. Зачем преобразовывать PChar в PChar?
2. О каких строках речь?


 
Сергей М. ©   (2007-11-12 09:04) [2]

1. Абсолютно корректно.

2. Смотря как строка объявлена.


 
KSergey ©   (2007-11-12 09:07) [3]

> Anatoly Podgoretsky ©   (12.11.07 09:02) [1]
> 1. Зачем преобразовывать PChar в PChar?

Вот это не понял. В смысле - компилятор и так догадается?


 
KSergey ©   (2007-11-12 09:10) [4]

> Anatoly Podgoretsky ©   (12.11.07 09:02) [1]
> 2. О каких строках речь?
> Сергей М. ©   (12.11.07 09:04) [2]
> 2. Смотря как строка объявлена.

Тут меня интересуют 2 варианта (пишу буквально вызовы):

//--- Вариант 1 ---
  SomeProc("SomeString");

//--- Вариант 2 ---
var  S: String
.....
  SomeProc(S);


 
Anatoly Podgoretsky ©   (2007-11-12 09:35) [5]


> В смысле - компилятор и так догадается?

Ему догадываться не надо, когда это явно указано в прототипе.

По вариантам, во втором надо преобразование, по терминологии приведение.


 
Однокамушкин   (2007-11-12 09:47) [6]

Строковые литералы явно приводить к PChar не только не нужно, но даже вредно: в случае литератлов из нескольких символов вы получаете абсолютно такой же код, в случае литерала из одного символа вы получаете access violation... Попробуйте вызвать процедуру вот так SomeProc(PChar("A")) - будет AV... прикол в том, что когда односимвольный литерал используется без явного приведения к типу PChar, компилятор по типу формального параметра понимает, что здесь требуется строка и рассматривает литерал как строковый, а когда между литералом и функцией появляется прослойка в виде приведения типа, компилятор не может оперделить, строковое значение здесь требуется или символьное, и рассматривает односимвольный литерал как символ... Приведение такого литерала к типу PChar призводится так же, как и любого порядкового типа к любому указателю, т.е. берётся численное значение и делается указатель с таким адресом, т.е. например, если литерал равен "A", код этого символа 65 (он же $41), PChar("A") даст вам указатель $00000041, а любые манипуляции с таким указателем приводят к AV

Что касается переменных типа string, то их приведение к PChar обязательно, компилятор по-другому просто не понимает


 
Сергей М. ©   (2007-11-12 09:53) [7]


> //--- Вариант 1 ---
>   SomeProc("SomeString");


При компиляции под строку "SomeString" будет выделен блок (включая терминирующий #0) в секции иниц.данных модуля, адрес начала блока передан параметром при вызове процедуры. Этот адрес и есть ничто иное как неявный pchar-указатель.


> //--- Вариант 2 ---
> var  S: String
> .....
>   SomeProc(S);


Такую конструкцию компилятор не пропустит из-за ее неоднозначности, поэтому требуется приведение типа:

SomeProc(PChar(S))

Такая конструкция инструктирует компилятор рассматривать в кач-ве pchar-параметра начальный адрес буфера строки.


 
KSergey ©   (2007-11-12 10:01) [8]

Всем спасибо за разъяснения. Вопрос снят.


 
Однокамушкин   (2007-11-12 10:19) [9]


> Сергей М. ©   (12.11.07 09:53) [7]
> При компиляции под строку "SomeString" будет выделен блок
> (включая терминирующий #0) в секции иниц.данных модуля,
> адрес начала блока передан параметром при вызове процедуры.
>  Этот адрес и есть ничто иное как неявный pchar-указатель.

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


 
Anatoly Podgoretsky ©   (2007-11-12 10:22) [10]

> Однокамушкин  (12.11.2007 10:19:09)  [9]

Это так, поскольку это константа и ее помещают в константную область, в данном случае кода или его заменителся. Программист не имеет право изменять ее значение.


 
KSergey ©   (2007-11-12 11:35) [11]

> Anatoly Podgoretsky ©   (12.11.07 10:22) [10]
> Это так, поскольку это константа и ее помещают в константную
> область, в данном случае кода или его заменителся. Программист
> не имеет право изменять ее значение.

Во-во. На то и напоролися :)
Одно не понятно: версия дельфи не менялась, равно как и UPdates не ставились, а такая "трабла" вылезла...
Есть подозрение на изменившиеся свойства проекта.


 
Anatoly Podgoretsky ©   (2007-11-12 11:51) [12]

Тебе не кажется смешным изменять константу? Это только Борланд пошел на такие извращения.


 
KSergey ©   (2007-11-12 12:10) [13]

> Anatoly Podgoretsky ©   (12.11.07 11:51) [12]
> Тебе не кажется смешным изменять константу? Это только Борланд
> пошел на такие извращения.

Да я все понимаю.
Но проект в таком виде работал до меня не один год, и менял(?) себе константы преспокойно, а тут пришел я - и оно начало ломаться. Может и смешно, но досадно ведь.


 
guav ©   (2007-11-12 12:20) [14]

> Это только Борланд пошел на такие извращения.

Не только Борланд, с литералами и в С проблемы.

#include <string.h>

int main(void)
{
 char str1[] = "hello world !";
 char * str2 = "hello world !";
 strcpy(str1,  "that"s okay");
 strcpy(str2,  "crash"); // здесь пытаемся писать в константный буфер.
}



> [13] KSergey ©   (12.11.07 12:10)

Может раньше была вин98 или другая старая система, где можно было ?


 
Anatoly Podgoretsky ©   (2007-11-12 12:21) [15]

> KSergey  (12.11.2007 12:10:13)  [13]

Чтобы не было смешно - изучаем теория, хотя бы в части Константы


 
Anatoly Podgoretsky ©   (2007-11-12 13:04) [16]

> guav  (12.11.2007 12:20:14)  [14]

Я не про эти извращения, здесь все понятно - недостаточные знания.
Я про такие

const
 Name = X;

Name := NewX



Страницы: 1 вся ветка

Текущий архив: 2007.12.09;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.025 c
2-1195002111
evn
2007-11-14 04:01
2007.12.09
Как написать программу:Замена символов на другие символы


15-1194534907
Alral
2007-11-08 18:15
2007.12.09
MSXML 4.0 SP2 Setup


15-1194591394
Gydvin
2007-11-09 09:56
2007.12.09
Траблы с сетевым сканером


15-1194700737
Kostafey
2007-11-10 16:18
2007.12.09
С днем рождения ! 10 ноября


15-1194470055
Malik
2007-11-08 00:14
2007.12.09
Повтарюсь:"Язык, на котором был написан виндовз"