Собственно почему *s\s выдаёт ошибку а не стррку с памяти?
*s.string=@"34556666666" Debug PeekS(*s,-1,#PB_Unicode) Debug *s\s
Отредактировано Sergeihik (14.10.2023 10:45:39)
PureBasic - форум |
Привет, Гость! Войдите или зарегистрируйтесь.
Вы здесь » PureBasic - форум » Вопросы по PureBasic » Вопрос по строке
Собственно почему *s\s выдаёт ошибку а не стррку с памяти?
*s.string=@"34556666666" Debug PeekS(*s,-1,#PB_Unicode) Debug *s\s
Отредактировано Sergeihik (14.10.2023 10:45:39)
Собственно почему *s\s выдаёт ошибку а не стррку с памяти?
Потому что адрес строки присваивается указателю экземпляра структуры, а не строке.
Так работать не будет.
Потому что адрес строки присваивается указателю экземпляра структуры, а не строке.
Так работать не будет.
Не правильно как то всё это, чисто с переменными же работает
*i.integer=AllocateMemory(100) PokeI(*i,455555) Debug PeekI(*i) Debug *i\i FreeMemory(*i)
Целочисленная переменная находится непосредственно в структуре, т. к. ее размер известен. Строка может иметь различный размер и в структуре находится указать на нее. Память под строку нужно выделять/освобождать.
А где тогда хранится строковый литерал "34556666666"? Не в памяти, что ли?
Замабувараев
что за строковый литерал? Если у строки есть конкретная длина-константа, то такая строка вроде может быть указатель сразу на строку. Например массив строк-констант является последовательностью прилегающих друг к другу данных, а массив строк неизвестной длины является массивом указателей на строки. Внутреннюю кухню можно предполагать. Буква в одинарных кавычках фактически число-код буквы:
Debug Asc("a") Debug 'a'
оба вернут 97
литерал это не строка.
Sergeihik
Сколько я использую структуры, вот что я понял: если мы передаём структуру в функцию, то тогда мы используем звёздочку внутри функции (ещё при выделении памяти AllocateMemory + InitializeStructure), а если мы создаём структуру по ходу пьесы в одном пространстве, то не используем звёздочку. Видимо передача в функцию сама инициализирует память для функции и делает структуру как указатель и не очищает данные. Когда создаёшь структуру внутренний механизм сам определяет что куда положить, здесь s\s это элемент структуры, а "s" или *s это не указатель на строку. То что PeekS её прочитал, так только потому что указатель воткнут в указатель структуры и там остался, а PeekS прочитал с этого указателя, а попробуй манипулировать данными, чтобы произошло перевыделение памяти, это как если поменять расширение у файла html на zip, от этого файл не откроется как архив, так и структура содержит невалидный указатель, какие-то бинарные данные, которые не ссылаются ни на что, а то что PeekS это прочитал это не показатель валидности данных, а только показатель что в якобы в структуре указатель на строку, которую он прочитал.
Define s.String s\s = "34556666666" t = PeekI(s) ; это указатель t в указателе s Debug PeekS(t, -1, #PB_Unicode) ; в указателе t данные на строку
указатель например 8 байт (в x64), в твоём примере он из числа "34556666666" возьмёт первые 8 байт в бинарном виде и воспримет их как указатель, но они могут ссылаться за пределы области выделенной памяти для программы.
Пример из справки, надо создать указатель на указатель, тогда будет работать.
*Text = @"Hello" *Pointer.String = @*Text Debug *Pointer\s
На сколько я понимаю строка "Hello" останется неприкосновенной в программе, а механизм структуры перевыделит память если будет записана строка более длинными данными.
Отредактировано AZJIO (16.10.2023 16:30:33)
А где тогда хранится строковый литерал "34556666666"?
Нужно конкретизировать вопрос.
Желательно вместе с кодом.
А где тогда хранится строковый литерал "34556666666"? Не в памяти, что ли?
Все хранится в памяти включая константы.
Видимо передача в функцию сама инициализирует память для функции и делает структуру как указатель и не очищает данные.
Передача по указателю это не передача по значению.
В первом случае передается адрес в памяти (копирование данных структуры не производится) и изменение затрагивает оригинальные данные.
В втором случае, создается копия данных и изменение копии на оригинальные данные не влияет.
На сколько я понимаю строка "Hello" останется неприкосновенной в программе, а механизм структуры перевыделит память если будет записана строка более длинными данными.
Нет.
*Text = @"Hello" *Pointer.String = @*Text Debug *Pointer\s Debug "Hello" PokeS(@*Pointer\s, "1234") Debug *Pointer\s Debug "Hello" ; Будет "1234"
Собственно почему *s\s выдаёт ошибку а не стррку с памяти?
Потому что строковый тип это нечто большее, чем просто указатель на некую любую область памяти.
Возможный аналог с другими языками программирования - "объект типа string".
Нет.
Потому что пере выделение памяти не происходит. Также интересно - строка является частью тела программы, то есть не динамическое пространство памяти выделенное программе. Если писать данные в тело программы это в каком то виде нарушение исполняемого файла.
Если писать данные в тело программы это в каком то виде нарушение исполняемого файла.
Загруженного в память.
На диске содержимое файла не меняется.
Пётр
Я считал что исполняемая часть кода загруженная в память не меняется. То есть все переменные меняются непосредственно в теле программы и не создаёт их копий?
Не проще ли посмотреть, что там генерирует компилятор?
В asm в секции .data будет инструкция ассемблера DW, определяющая содержимое строки плюс завершающий ноль. И да, строку можно изменить записав туда по адресу что-нибудь.
Я считал что исполняемая часть кода загруженная в память не меняется.
Содержимое памяти можно изменить.
Исполняемый файл не грузится в память как он есть на диске, а загружается по секциям. Это позволяет к примеру загрузить секцию .code в одном экземпляре для всех запущенных копий приложения, а другие секции содержащие константы и переменные, будут загружены для каждой копии в отдельности.
То есть все переменные меняются непосредственно в теле программы
Несмотря на то, что в файле исходного кода переменные и код смешаны, в скомпилированном екзешнике ничего не смешано.
Переменные и код разнесены по разным секциям.
Код хранится в специальных секциях, переменные — в стеке или в других секциях. Меняя переменные вы меняете только байты в стеке, секции кода при этом не затрагиваются.
Потому что адрес строки
А в чём отличие этого кода от того что это адрес динамической памяти присвоенный указателю структуры(а не программной секции)
ну и по указателю структуры записана строка ,только вот тогда peeks(нужно указатель на указатель)?
Global *s.string=AllocateMemory(50) *s\s="34556666666"; Debug *s\s Debug PeekS(@*s\s,-1,#PB_Unicode) FreeMemory(*s.string) ;предыдущий код *s.string=@"34556666666" Debug PeekS(*s,-1,#PB_Unicode) Debug *s\s ;;;;;;;;;;;;;;;;;
Sergeihik
Указателю структуры строки должен присваиваться указатель на существующую строку. В указателе храниться указатель на строку, его ширина 8 байт, для указателя строки не нужно выделать 50 байт с отсутствием указателя на саму строку. Как это будет работать? Это разные типы. В одном случае указатель на выделенную память, в другом случае указатель на структуру. Они разные по содержимому/устройству.
AllocateMemory(50) выделяет 50 байт и даёт пользователю указатель на позицию где эти 50 байт начинаются. Структура это указатель на указатель строки, то есть указатель на 8 байт в котором находится указатель на строку. Если его поместить в 50 байт, то первые 8 байт будет пустым, а там должен быть указатель, остальные 42 байта будут бессмысленным прицепом. А строки вообще не будет. И Windows не сможет обратиться к данным (к строке), так как скажет что указателя "0" не существует.
Отредактировано AZJIO (12.11.2023 19:23:44)
Sergeihik, ваш код работать не будет.
Чтобы он работал, структура должна содержать строку фиксированного размера.
Structure str s.s{100} EndStructure *s.str=AllocateMemory(SizeOf(str)) *s\s="34556666666"; Debug *s\s Debug PeekS(@*s\s,-1,#PB_Unicode) FreeMemory(*s) ;предыдущий код *s=@"34556666666" Debug PeekS(*s,-1,#PB_Unicode) Debug *s\s
Указателю структуры строки должен присваиваться указатель на существующую строку. В указателе храниться указатель на строку, его ширина 8 байт, для указателя строки не нужно выделать 50 байт с отсутствием указателя на саму строку. Как это будет работать? Это разные типы. В одном случае указатель на выделенную память, в другом случае указатель на структуру. Они разные по содержимому/устройству.
AllocateMemory(50) выделяет 50 байт и даёт пользователю указатель на позицию где эти 50 байт начинаются. Структура это указатель на указатель строки, то есть указатель на 8 байт в котором находится указатель на строку. Если его поместить в 50 байт, то первые 8 байт будет пустым, а там должен быть указатель, остальные 42 байта будут бессмысленным прицепом. А строки вообще не будет. И Windows не сможет обратиться к данным (к строке), так как скажет что указателя "0" не существует.
Какая то зацикленность у вас на 8 байт указателя,а нечего что винда у меня х32=4 байта адресация памяти?
По вашей логике указатель на указатель тогда и структура наверное должна быть
Structure String *wstr EndStructure а не Structure String s.s EndStructure
и как тогда работать с структурой string если надо прочитать строку и записать в память=никак?
или так по чудному как то?
*s1=AllocateMemory(50) PokeS(*s1,"34556666666",-1,#PB_Unicode) *s.string=@*s1 Debug *s\s For i=0 To 26 Step 2 Debug PeekU(@*s\s+i) Next Debug PeekS(@*s\s,-1,#PB_Unicode) FreeMemory(*s1) ;============================= *s4=@"34556666666" *s3.string=@*s4 Debug PeekS(@*s3\s,-1,#PB_Unicode) Debug *s3\s
Только записать тогда как в память?
Отредактировано Sergeihik (13.11.2023 00:26:08)
,а нечего что винда у меня х32=4 байта адресация памяти?
Ну хоть в чём то я не прав, что не угадал ОС неизвестного мне компа, хотя это и не была необходимая цель для показа работы строки.
Код:*s1=AllocateMemory(50) PokeS(*s1,"34556666666",-1,#PB_Unicode) *s.string=@*s1
Чтобы получить решение надо определиться каким способом будут получены данные. Чтобы создать строку с данными "34556666666" надо просто str$ = "34556666666". Если это данные в памяти, то надо читать с помощью PeekS(). Если это уже строка то используется приравнивание str$ = "34556666666". Структура *s.String по смыслу та же строка, все действия с ней выполняются также как с переменной str$, то есть поле *s.\s равнозначно str$, но с разницей, строку можно отправить в функцию по указателю, то есть отправить указатель на структуру *s, а в приёмнике указать создание структуры *s.String и внутри функции использовать *s.\s, тогда не происходит копирование строки при передачи данных. При этом к этой динамической строке нельзя относится как к бесконечному буферу, даже если строка передана как буфер в функцию WinAPI, то надо гарантировать что данные в неё войдут, то есть используется Space(), чтобы создать строку нужной длины для последующего использования её как буфера, то есть после вброса данных в неё, с ней можно продолжать работать как со строкой, а при использовании AllocateMemory(50) ты не получаешь строку, ты получаешь область памяти и не можешь работать с этими данными как со строкой. При чём причин несколько, например при использовании PeekS() ты создаёшь переменную, но этот процесс не просто чтение одних данных из памяти в другую часть памяти и хотелось бы просто одни данные как то преобразовать в другие не копируя, но PeekS() ещё и переводит данные в "компьютерный" формат строки, то есть если 3-им параметром стоит #PB_UTF8 или #PB_Ascii, то данные будут ещё и преобразованы в формат #PB_Unicode. То есть если тупо использовать переменную с заданной длинной {100} и взять указатель на данные в формате #PB_UTF8 или #PB_Ascii и приравнять их к переменной, то данные внутри переменной при выводе окажутся другими и поиск FindString() по ним работать не будет при кажущейся удаче.
Код:For i=0 To 26 Step 2 Debug PeekU(@*s\s+i) Next
Перебор строки посимвольно я уже делал в куче функций разными способами, буквально вчера сделал человеку побайтам предлагая перед этим посмотреть готовые примеры. Но при отсутствии реакции если человеку сложно было перестроить посимвольный пример в побайтовый, то дал готовый пример.
Отредактировано AZJIO (13.11.2023 10:43:26)
винда у меня х32=4 байта адресация памяти
Сейчас это редкость, потому что 4 ГБ ОЗУ мало.
По вашей логике указатель на указатель тогда и структура наверное должна быть
Примерно так и выглядит. Только указатель скрытый и работа с ним средствами PB.
и как тогда работать с структурой string если надо прочитать строку и записать в память=никак?
Работайте со строкой средствами PB. Если не вариант, переходите на указатели.
Не зная задачи сложно что-то посоветовать.
Structure Ch_ _ch.u[0] ; есть такой приём EndStructure Define teststr.s Define *pch.Ch_ Define i = 0 teststr = "0123456789qwertyйцукен" *pch = @teststr ; это даёт правильный адрес, нужно только понимать, ; что например после teststr = teststr + "___" он может стать другим ; и его желательно получать каждый раз перед использованием While (*pch\_ch[i] <> 0) Debug RSet(Hex(*pch\_ch[i],#PB_Unicode), 4, "0") : i+1 Wend
Сейчас это редкость, потому что 4 ГБ ОЗУ мало.
Да лучше 4гб и проц нормальный относительно чем тормаза на х64 с памятью(на работе купили х64 с виндой 11
так тормозит конкретно,даже файл пурика компилит с 10 раза иначе ошибка(наверное типа время задачи (процесса)истекло?),),пока скомпилит нормально минут 10-20 уходит.......
Отредактировано Sergeihik (06.12.2023 20:12:09)
useful
Тоже трюк.
ps: только с датасекцией или напутал чего или фасм (может пурик)ложит туда utf-8?
Pss:Это говорит о том что возможность есть так взять типа по offset?
но со структурой string пурик этого не делает.
Global s.s Procedure.s Getstroka(*adres) !mov dword eax,[p.p_adres] !mov dword [v_s],eax ProcedureReturn s EndProcedure Global *stroka=AllocateMemory(500) PokeS(*stroka,"34556666666",-1,#PB_Unicode) Debug PeekS(*stroka,-1,#PB_Unicode) Debug Getstroka(*stroka) PokeS(*stroka,"8iugyuiа46гатраytyi7yyhjygn======Privet это динамическая строка========gро5ираавмор",-1,#PB_Unicode) Debug Getstroka(*stroka) Debug Getstroka(?statihescay_stroka) FreeMemory(*stroka) DataSection statihescay_stroka: !du '8iugyuiytyi7yyhjygn======Privet=Это статическая строка!======giggddhffyhh',0 EndDataSection
Отредактировано Sergeihik (06.12.2023 20:06:37)
но со структурой string пурик этого не делает.
И не должен.
Чтобы так работало строка должна быть фиксированного размера Вопрос по строке
Вы здесь » PureBasic - форум » Вопросы по PureBasic » Вопрос по строке