FreeBasic
Главная
Вход
Регистрация
Четверг, 14.05.2026, 15:19Приветствую Вас Гость | RSS
[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 2 из 3
  • «
  • 1
  • 2
  • 3
  • »
Сравнение указателей может дать неожиданный результат
zamabuvaraeuДата: Воскресенье, 19.04.2026, 16:15 | Сообщение # 16
Полковник
Группа: Друзья
Сообщений: 210
Репутация: 5
Статус: Offline

Цитата
По странному стечению обстоятельств найти в Интернете стандарт на язык Си не так то просто. Похоже, что комитет ISO распространяет варианты
этого стандарта за деньги, и сознательно скрывает информацию, где
таковой стандарт можно получить в открытом виде.
Любые бумажные журналы и газеты так работают.
Научная литература тоже публикуется в научных журналах, и без подписки (то есть без оплаты) их нигде нет. Поэтому библиотеки от университетов для профессоров, кандидатов и доцентов и желающих закупают журналы.
 
haavДата: Воскресенье, 19.04.2026, 16:44 | Сообщение # 17
Генералиссимус
Группа: Администраторы
Сообщений: 1474
Репутация: 50
Статус: Offline
Цитата DarkDemon ()
Но можно, наверное, скаститьуказатель в число и там уже сравнить, с этим то проблем надеюсь нет?

Да можно , я об этом написал выше. Судя по всему,  других 100% работающих способов сравнить указатели больше нет.

Цитата DarkDemon ()
Написанное, по ощущениям, просто свободным языком, в случайной последовательности, человеком с рассеянным склерозом.Называть это чем-то базо-образующим - трудно, работать с этими документами - можно бошкой двинуться...

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


Цитата
Научная литература тоже публикуется в научных журналах, и без подписки (то есть без оплаты) их нигде нет.

Кругом одна меркантильщина.


Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
 
zamabuvaraeuДата: Воскресенье, 19.04.2026, 18:33 | Сообщение # 18
Полковник
Группа: Друзья
Сообщений: 210
Репутация: 5
Статус: Offline

Код
#include once "crt.bi"

Dim a As Integer = Any
Dim p As Integer Ptr = @a

Dim q As Integer Ptr = Any
memcpy(@q, @p, SizeOf(Integer Ptr))

Print Hex(p), Hex(q), p = q
Этот код показывает что указатели равны, что и следовало ожидать.
 
DarkDemonДата: Понедельник, 20.04.2026, 00:13 | Сообщение # 19
Генерал-майор
Группа: Друзья
Сообщений: 328
Репутация: -1
Статус: Offline
Понятно что ты просто отвязал от b, для компиля это как красная тряпка для быка.

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

Код
ASM
    MOV rbx, q
END ASM

Но я честно не знаю как это постоянно при кодинге можно держать в голове, всмысле этот "стандарт".
Да никак ты это не удержишь, это просто дерьмо)))

Добавлено (20.04.2026, 00:43)
---------------------------------------------
Т.е. никакой нормальной пилюли нет. Либо отвязка - что = правка кода, либо говноасм, что либо сломает оптимизацию
либо кроссплатформу.

Цитата
Наверное, это пришло в голову создателям x86 в реальном режиме. Где XXX хранятся в одном сегменте, и YYY хранятся в другом сегменте.

Мне кажется это не относится к сегментации РР. Это хард архитектура, как бы "одна из". Там раньше дерьма много было
в т.ч. и пресловутые 64кб страницы( в банках VESA \ параметрах DMA). Можно считать это просто особенностью архитектуры.
Почему так сделали мало кто из программистов скажет, это надо спрашивать у тех кто первые intel-ы разрабатывал.

Кстати CAST-ами у кого получилось вылечить? У меня не получилось! ))) Всё перепробовал, даже через булевые
операции(XOR, AND и т.п.), эта сука как-то понимает то что мы хотим сделать и не даёт сравнить эти вещи как числовые значения.

Добавлено (20.04.2026, 01:00)
---------------------------------------------
А вот получилось кое чего. Но уровень "корявости" восхищает:



Код
IIF((CINT(p) XOR CINT(q)) > 0 , 0, -1)

Добавлено (20.04.2026, 01:17)
---------------------------------------------
Ну и не спрашивайте почему не CUINT, оно сука, понимает что мы хотим сделать, меняет логику сравнения
и всё что в неё входит, т.е. ломает любую булеву логику выражения. Т.е. чисто теоретически через XOR оно
может и не сработать из-за именно диапазонов чисел. Наверное это может произойти на каких-то прям
больших числах, но в целом по переходу границы в 8589934591 Гб оперативки, у людей столько пока нет))).

Добавлено (20.04.2026, 01:19)
---------------------------------------------
Ну и да ещё стоит учитывать, что от компилятора к компилятору результат вероятно может меняться  happy 
это добавляет веселухи во весь этот процесс.

 
haavДата: Понедельник, 20.04.2026, 06:34 | Сообщение # 20
Генералиссимус
Группа: Администраторы
Сообщений: 1474
Репутация: 50
Статус: Offline
Цитата DarkDemon ()
Кстати CAST-ами у кого получилось вылечить? У меня не получилось!

У меня так сравнивает правильно:


Код
Print Hex(p), Hex(q), cint(p) = cint(q)

Если у тебя неправильно , обрати пристальное внимание на совпадение адресов.


Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
 
DarkDemonДата: Понедельник, 20.04.2026, 08:44 | Сообщение # 21
Генерал-майор
Группа: Друзья
Сообщений: 328
Репутация: -1
Статус: Offline
Цитата haav ()
Если у тебя неправильно , обрати пристальное внимание на совпадение адресов.


Кроличья нора оказалась глубже чем я думал. После первых тестов посчитал, что O 3 и O 1 дают одинаковый результат.
А на деле хрен там пел. cint(p) = cint(q) работает только на O 1, на O 3 - уже нет! Так что это какой-то песец)))
Прикиньте сколько головняка можно отхватить на этих оптимайзах))) Даже представить боюсь...

https://rutube.ru/video/bdb2ab0040f57ebaf0d581c63f6b1f8b/
 
haavДата: Понедельник, 20.04.2026, 14:48 | Сообщение # 22
Генералиссимус
Группа: Администраторы
Сообщений: 1474
Репутация: 50
Статус: Offline
Цитата
А на деле хрен там пел. cint(p) = cint(q) работает только на O 1, на O 3 - уже нет!

Возможно адреса при разных оптимизациях меняются (становятся не равными) и ты этого не замечаешь. Там бывает разница в одной букве или цифре , а 64-bit адрес довольно длинный (циферок много). У меня при любом уровне оптимизации результат одинаковый (такой , какой я ожидаю).


Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
 
DarkDemonДата: Вторник, 21.04.2026, 02:42 | Сообщение # 23
Генерал-майор
Группа: Друзья
Сообщений: 328
Репутация: -1
Статус: Offline
Цитата haav ()
Возможно адреса при разных оптимизациях меняются (становятся не равными) и ты этого не замечаешь. Там бывает разница в одной букве или цифре


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

Код
DIM a AS INTEGER
DIM b AS INTEGER
DIM s1 AS STRING, s2 AS STRING

DIM p AS INTEGER PTR = @a
DIM q AS INTEGER PTR = @b + 1

s1 = HEX(p): s2 = HEX(q)
PRINT " HEXes:"
PRINT " "; s1, s2
IF s1 = s2 THEN COLOR 10: PRINT " EQUAL": COLOR 7: ELSE COLOR 12: PRINT " NOT EQUAL!!!": COLOR 7
PRINT " Result 1     : "; CINT(p) = CINT(q)
PRINT " Result 2     : "; IIF((CINT(p) XOR CINT(q)) > 0 , 0, -1)

SLEEP

Опция O 1:


Опция O 3 (чтобы адреса сравнялись пришлось писать DIM q AS INTEGER PTR = @b - 1):
Прикрепления: 7915348.png (5.6 Kb) · 0893621.png (5.6 Kb)


Сообщение отредактировал DarkDemon - Вторник, 21.04.2026, 02:53
 
haavДата: Вторник, 21.04.2026, 05:36 | Сообщение # 24
Генералиссимус
Группа: Администраторы
Сообщений: 1474
Репутация: 50
Статус: Offline
Ага. Если присвоить указателю адрес с последующим декрементом , то все так , как у тебя на скрине. Какое-то предупреждение вылезает от компилятора , что мы вышли за пределы массива...

Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
 
DarkDemonДата: Вторник, 21.04.2026, 08:06 | Сообщение # 25
Генерал-майор
Группа: Друзья
Сообщений: 328
Репутация: -1
Статус: Offline
Цитата haav ()
Ага. Если присвоить указателю адрес с последующим декрементом , то все так , как у тебя на скрине. Какое-то предупреждение вылезает от компилятора , что мы вышли за пределы массива...

Может я чё не так сделал, но на самом деле не совсем понимаю(суммарно) те правила стандарта, о которых писал
в первом посте Замабувараев. Перецитирую:

Цитата
* оба являются нулевыми
* либо указывают на один и тот же объект или функцию
* либо указывают на позицию за последним элементом массива
* либо один указатель ссылается на позицию за последним элементом массива, а другой — на начало другого массива, следующего сразу за первым в том же адресном пространстве

Тут самое малопонятное - третье.

Однако речь о том чтобы это ВСЁ проверять. Что-то можно проверить на этапе компиляции, но, во-первых, что-то 
подсказывает, что далеко не всё, а во-вторых, не особо понятно как это поможет в оптимизации.
Тут идёт какой-то идеологический разлом, указатели созданы чтобы с ними работали, меняли их значения.
И привязка к какому-то конкретному массиву или объекту выглядит довольно глупо, т.к. сам указатель и создан
чтобы ДИНАМИЧЕСКИ менять значения и указывать на разные вещи.
По сути мы имеем дело с отчуждением свойств самих указателей, мол пофиг куда они там смотрят, но
ИЗНАЧАЛЬНО они смотрели куда-то там сюда и сюда и поэтому мы вместо условия проверки подставим готовое
значение. Ну тут логика хромает на обе ноги(насколько, например, понимаю последний пункт - "неравны априори"
используется как одно из условий влияющих на результат из-за чего и возникает вся эта жопа).
Причём да, связью с моделями памяти тут нет. Т.е. мешается всё в одну кучу и указатели как стрелочки на что-то на
листе бумаги(т.е. указатели не на байты, а просто на что-то) и указатели как реальные адреса памяти, реальной
размерности бит, указывающие в любое место на конкретные байты согласно типизации.
 
zamabuvaraeuДата: Вторник, 21.04.2026, 11:06 | Сообщение # 26
Полковник
Группа: Друзья
Сообщений: 210
Репутация: 5
Статус: Offline
Вот вам простой пример, где указатели разные, а память на которую они указывают — совпадает:

Код
#include once "windows.bi"

Private Function FindFreeAddress( _
      ByVal dwSize As UInteger _
   )As LPVOID
   
   Dim lpBaseAddress As LPVOID = VirtualAlloc( _
      NULL, _
      dwSize, _
      MEM_RESERVE, _
      PAGE_READWRITE _
   )
   
   If lpBaseAddress Then
      VirtualFree(lpBaseAddress, 0, MEM_RELEASE)
   End If
   
   Return lpBaseAddress
   
End Function

Private Function GetAllocationGranularity() As DWORD
   
   ' узнаём размер гранулы
   Dim info As SYSTEM_INFO = Any
   GetSystemInfo(@info)
   
   Return info.dwAllocationGranularity
   
End Function

Private Function RingBufferInitialize( _
      ByVal DesiredCapacity As UInteger, _
      ByVal ppFirstPage As UByte Ptr Ptr, _
      ByVal ppSecondPage As UByte Ptr Ptr _
   )As HRESULT
   
   ' VirtualAlloc создаёт память с округлением до гранулы
   
   Dim dwGranularity As DWORD = GetAllocationGranularity()
   
   Dim Capacity As UInteger = ((DesiredCapacity \ Cast(size_t, dwGranularity)) + 1) * dwGranularity
   
   Dim hMapFile As HANDLE = Any
   Scope
      Dim ulBufferSize As ULARGE_INTEGER = Any
      ulBufferSize.QuadPart = Capacity * 2
      
      hMapFile = CreateFileMapping( _
         INVALID_HANDLE_VALUE, _
         NULL, _
         PAGE_READWRITE, _
         ulBufferSize.HighPart, ulBufferSize.LowPart, _
         NULL _
      )
      If hMapFile = NULL Then
         Dim dwError As DWORD = GetLastError()
         *ppFirstPage = NULL
         *ppSecondPage = NULL
         
         Return HRESULT_FROM_WIN32(dwError)
      End If
   End Scope
   
   ' Ищем свободный адрес (несколько попыток)
   Const StepsCount = 10
   
   For i As Integer = 0 To StepsCount - 1
      Dim lpBaseAddress1 As LPVOID = FindFreeAddress( _
         Capacity * 2 _
      )
      
      If lpBaseAddress1 Then
         
         Dim pFirstRegion As UByte Ptr = MapViewOfFileEx( _
            hMapFile, _
            FILE_MAP_READ Or FILE_MAP_WRITE, _
            0, 0, _
            Cast(DWORD, Capacity), _
            lpBaseAddress1 _
         )
         
         If pFirstRegion Then
            
            Dim lpBaseAddress2 As LPVOID = Cast(LPVOID, (CPtr(UByte Ptr, lpBaseAddress1) + Capacity))
            
            Dim pSecondRegion As UByte Ptr = MapViewOfFileEx( _
               hMapFile, _
               FILE_MAP_READ Or FILE_MAP_WRITE, _
               0, 0, _
               Cast(DWORD, Capacity), _
               lpBaseAddress2 _
            )
            
            If pSecondRegion Then
               
               *ppFirstPage = pFirstRegion
               *ppSecondPage = pSecondRegion
               
               Return S_OK
            End If
            
            UnmapViewOfFile(pFirstRegion)
         End If
         
      End If
      
   Next
   
   *ppFirstPage = NULL
   *ppSecondPage = NULL
   
   CloseHandle(hMapFile)
   
   Return E_OUTOFMEMORY
   
End Function

Const HelloWorld = __TEXT("Hello World")

Dim pFirstPage As Any Ptr = Any
Dim pSecondPage As Any Ptr = Any
Dim hr As HRESULT = RingBufferInitialize( _
   100, _
   @pFirstPage, _
   @pSecondPage _
)
If FAILED(hr) Then
   End(1)
End If

' Записываем данные во вторую страницу
memcpy(pSecondPage, @HelloWorld, (Len(HelloWorld) + 1) * SizeOf(TCHAR))

' и читаем данные из первой страницы
' проверяем: данные совпадают
Print *(Cast(LPTSTR, pFirstPage))
Print *(Cast(LPTSTR, pSecondPage))

' однако указатели разные
Print Hex(pFirstPage), Hex(pSecondPage)
 
haavДата: Вторник, 21.04.2026, 12:25 | Сообщение # 27
Генералиссимус
Группа: Администраторы
Сообщений: 1474
Репутация: 50
Статус: Offline
Цитата
Вот вам простой пример, где указатели разные, а память на которую они указывают — совпадает:


Не понял , зачем было так городить?
Вот тоже данные одинаковые , но указатели разные:


Код
Const HelloWorld = "Hello World" 
dim as Integer iLen = len(HelloWorld) 
 
Dim pFirstPage As zstring Ptr = callocate(iLen+1) 
Dim pSecondPage As zstring Ptr = callocate(iLen+1) 
 
*pFirstPage = HelloWorld 
*pSecondPage = HelloWorld 
 
Print *pFirstPage 
Print *pSecondPage 
 
Print Hex(pFirstPage), Hex(pSecondPage)


Вы сохраняете власть над людьми покуда оставляете им что-то…Отберите у человека все, и этот человек уже будет неподвластен вам…
 
zamabuvaraeuДата: Вторник, 21.04.2026, 14:02 | Сообщение # 28
Полковник
Группа: Друзья
Сообщений: 210
Репутация: 5
Статус: Offline

Цитата
Не понял , зачем было так городить?
Обрати внимание: записываем данные по первому указателю, а потом данные читаем по второму указателю — и они там волшебным образом появляются.

Добавлено (21.04.2026, 14:04)
---------------------------------------------
Наоборот конечно, но это не важно
Записываем туда, читаем отсюда — чёрная магия

 
DarkDemonДата: Вторник, 21.04.2026, 16:03 | Сообщение # 29
Генерал-майор
Группа: Друзья
Сообщений: 328
Репутация: -1
Статус: Offline
Цитата zamabuvaraeu ()
Наоборот конечно, но это не важноЗаписываем туда, читаем отсюда — чёрная магия

Там внутри что-то с маппингами, ведь оно это делает, а не то, что в стартовом сообщении озвучено?
 
zamabuvaraeuДата: Среда, 22.04.2026, 03:22 | Сообщение # 30
Полковник
Группа: Друзья
Сообщений: 210
Репутация: 5
Статус: Offline
В том коде мы проецируем две виртуальные страницы памяти на одну физическую. В итоге имеем два разных указателя, которые ссылаются на одну и ту же память. Такое часто используется для кольцевого буфера.
 
  • Страница 2 из 3
  • «
  • 1
  • 2
  • 3
  • »
Поиск: