![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Передача строки в параметр PChar
KSergey © (2007-11-12 08:47:00)Имеем процедуру:
procedure SomeProc(AStr: PChar);
Вызываем ее так:
SomeProc('SomeString');
Компиялтор не ругается и вроде даже все работает (т.е. в ыункция приезжает то, что и ожидалось и в строке внутри процедуры завершающий нуль присутствует). Но по косвенному признаку вдруг закралось подозрение: все ли тут хорошо?
Что собственно беспокоит:
1) Действительно ли корректно передавать строку в параметр PChar без явного преобразования PChar('SomeString')? Я понимаю, что это предбрпзование отчасти фейковое и вроде явного вызова какой-либо процедуры не происходит, но все же?
2) Всегда ли строки в дельфи хранятся с завершающим нулевым символом?
Я понимаю, что "практика - критерий истины", но может кто подскажет место, где эти моменты явно написаны? Куски кода, формирующего строки, например - вполне подойдут.
Anatoly Podgoretsky (2007-11-12 13:04:00) [1]> guav (12.11.2007 12:20:14) [14]
Я не про эти извращения, здесь все понятно - недостаточные знания.
Я про такие
const
Name = X;
Name := NewX
Anatoly Podgoretsky (2007-11-12 12:21:00) [2]> KSergey (12.11.2007 12:10:13) [13]
Чтобы не было смешно - изучаем теория, хотя бы в части Константы
guav (2007-11-12 12:20:00) [3]> Это только Борланд пошел на такие извращения.
Не только Борланд, с литералами и в С проблемы.
#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 или другая старая система, где можно было ?
KSergey (2007-11-12 12:10:00) [4]> Anatoly Podgoretsky © (12.11.07 11:51) [12]
> Тебе не кажется смешным изменять константу? Это только Борланд
> пошел на такие извращения.
Да я все понимаю.
Но проект в таком виде работал до меня не один год, и менял(?) себе константы преспокойно, а тут пришел я - и оно начало ломаться. Может и смешно, но досадно ведь.
Anatoly Podgoretsky (2007-11-12 11:51:00) [5]Тебе не кажется смешным изменять константу? Это только Борланд пошел на такие извращения.
KSergey (2007-11-12 11:35:00) [6]> Anatoly Podgoretsky © (12.11.07 10:22) [10]
> Это так, поскольку это константа и ее помещают в константную
> область, в данном случае кода или его заменителся. Программист
> не имеет право изменять ее значение.
Во-во. На то и напоролися :)
Одно не понятно: версия дельфи не менялась, равно как и UPdates не ставились, а такая "трабла" вылезла...
Есть подозрение на изменившиеся свойства проекта.
Anatoly Podgoretsky (2007-11-12 10:22:00) [7]> Однокамушкин (12.11.2007 10:19:09) [9]
Это так, поскольку это константа и ее помещают в константную область, в данном случае кода или его заменителся. Программист не имеет право изменять ее значение.
Однокамушкин (2007-11-12 10:19:00) [8]
> Сергей М. © (12.11.07 09:53) [7]
> При компиляции под строку 'SomeString' будет выделен блок
> (включая терминирующий #0) в секции иниц.данных модуля,
> адрес начала блока передан параметром при вызове процедуры.
> Этот адрес и есть ничто иное как неявный pchar-указатель.
Не знаю, как в других версиях Delphi, а в семёрке память для строковых литералов выделяется не в секции иниц.данных, а прямо в секции кода, сразу после той процедуры или функции, в которой этот литерал встретился... Впрочем, мы с вами уже спорили по этому вопросу
KSergey (2007-11-12 10:01:00) [9]Всем спасибо за разъяснения. Вопрос снят.
Сергей М. (2007-11-12 09:53:00) [10]
> //--- Вариант 1 ---
> SomeProc('SomeString');
При компиляции под строку 'SomeString' будет выделен блок (включая терминирующий #0) в секции иниц.данных модуля, адрес начала блока передан параметром при вызове процедуры. Этот адрес и есть ничто иное как неявный pchar-указатель.
> //--- Вариант 2 ---
> var S: String
> .....
> SomeProc(S);
Такую конструкцию компилятор не пропустит из-за ее неоднозначности, поэтому требуется приведение типа:
SomeProc(PChar(S))
Такая конструкция инструктирует компилятор рассматривать в кач-ве pchar-параметра начальный адрес буфера строки.
Однокамушкин (2007-11-12 09:47:00) [11]Строковые литералы явно приводить к PChar не только не нужно, но даже вредно: в случае литератлов из нескольких символов вы получаете абсолютно такой же код, в случае литерала из одного символа вы получаете access violation... Попробуйте вызвать процедуру вот так SomeProc(PChar('A')) - будет AV... прикол в том, что когда односимвольный литерал используется без явного приведения к типу PChar, компилятор по типу формального параметра понимает, что здесь требуется строка и рассматривает литерал как строковый, а когда между литералом и функцией появляется прослойка в виде приведения типа, компилятор не может оперделить, строковое значение здесь требуется или символьное, и рассматривает односимвольный литерал как символ... Приведение такого литерала к типу PChar призводится так же, как и любого порядкового типа к любому указателю, т.е. берётся численное значение и делается указатель с таким адресом, т.е. например, если литерал равен 'A', код этого символа 65 (он же $41), PChar('A') даст вам указатель $00000041, а любые манипуляции с таким указателем приводят к AV
Что касается переменных типа string, то их приведение к PChar обязательно, компилятор по-другому просто не понимает
Anatoly Podgoretsky (2007-11-12 09:35:00) [12]
> В смысле - компилятор и так догадается?
Ему догадываться не надо, когда это явно указано в прототипе.
По вариантам, во втором надо преобразование, по терминологии приведение.
KSergey (2007-11-12 09:10:00) [13]> 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);
KSergey (2007-11-12 09:07:00) [14]> Anatoly Podgoretsky © (12.11.07 09:02) [1]
> 1. Зачем преобразовывать PChar в PChar?
Вот это не понял. В смысле - компилятор и так догадается?
Сергей М. (2007-11-12 09:04:00) [15]1. Абсолютно корректно.
2. Смотря как строка объявлена.
Anatoly Podgoretsky (2007-11-12 09:02:00) [16]> KSergey (12.11.2007 08:47:00) [0]
1. Зачем преобразовывать PChar в PChar?
2. О каких строках речь?