• Тонкости Компиляторов. Почему в классах с++ не требуется объявление функции до вызова?

    @Mercury13
    Программист на «си с крестами» и не только
    Подозреваю, что объявление функции после вызова разрешили, потому что оно достаточно легко реализуемо, но даёт изрядную свободу прогеру. Например: несколько открытых конструкторов вызывают private init(), а этот init, как и все скрытые методы, сидит где-то в конце.

    Проходов компиляции может быть много — например, сначала мы говорим, что f(x) — это вызов, а вторым проходом определяем, с какой функцией f имеем дело. К тому же конкретно в Си++ любой код в теле класса — автоматический inline, то есть не создаёт кода, пока кто-то снаружи не вызовет.

    Умножение, приведение типа или ещё какая-то дрянь — это особенность метода разбора. Во многих языках, в том числе в Паскале, используется LL-разбор — сканирование слева направо, опознание слева направо. Ошибки наподобие «ожидалась точка с запятой» — это артефакт примитивных LL-анализаторов. В Си используется LR-разбор — сканирование слева направо, опознание справа налево, а ожидающие опознания лексемы хранятся в стеке.

    И вообще, если пишете собственный крайне специализированный язык, делайте его LL(1), это очень упростит разбор.

    Кстати, в Паскале принят обратный порядок видимости: private → protected → public → published. Последнее — поле доступно в рефлексии времени выполнения.
    Ответ написан
    Комментировать
  • Как можно инициализировать структуру в прямо в массиве в safe коде c#?

    AshBlade
    @AshBlade Куратор тега C#
    Просто хочу быть счастливым
    Сначала создает структуру на стеке, потом копирует ее в массив.


    Потому что сначала создается временная переменная с new User(1, 2), а потом она записывается в массив.

    Можно ли так сделать?


    Про так не знаю, но ты можешь использовать users.Initialize(). Он вызовет стандартный конструктор (без параметров) для всех элементов, а потом вручную выставить значения в цикле
    Ответ написан
    Комментировать
  • Что за формат чисел в ассемблерных файлах 000ABC100h в конце 'h', конкретно как парсить?

    mayton2019
    @mayton2019
    Bigdata Engineer
    Давай слегка тормознем твой поток созднания. Слишком много у тебя тезисов.
    В каждом языке программирования есть свои числовые литералы. В си-шарпе - свои.
    И в ассемблере свои.

    Попробуем ответить на первый.

    А могул ли быть, А100000000000000h, то есть начаться с А


    Да могут быть. В хекс-системе числа состоят из цифр и букв от A до F. Другое
    дело что ты должен следить за разрядностью и понимать что в регистр процессора
    (ассемблер) и тип данных (для шарпов) может влезать ограниченный диапазон
    величин. Например для ассемблерного двойного слова (DWORD) максимальное число FFFFFFFFh
    И для шарпового unsigned long максимальное 0xFFFF_FFFF_FFFF_FFFF

    Тоесть правильный ответ состоит из проверки числа на допустимые символы и проверки
    ТИПА данных на диапазон.
    Ответ написан
    4 комментария
  • Как при сборки мусора и перемещении объекта, сохраняется корректность ссылок?

    AshBlade
    @AshBlade Куратор тега C#
    Просто хочу быть счастливым
    Управление памятью в .NET для профессионалов

    Как работает сборка мусора.
    В .NET используется 2 фазная сборка мусора: Mark & Sweep (Пометить и Убрать).

    Mark

    На этом этапе обходится весь граф объектов. И выявляются все недостижимые.

    Каким образом достижимость объектов определяется?

    Достижимые это:
    - Аллоцированные на стеке
    - В статических полях
    - Достижимые из достижимых (см. выше)

    Все объекты, которые не удалось достичь (в граф не попали) - являются недостижимыми.

    Но на стеке лежат числа. могут быть как числами, так и адресами, как и числами?

    JIT копилятор достаточно умный, чтобы сгенерить код, который будет знать, что за объект/ссылка лежит на стеке. Так и получаются знания об объектах.

    Sweep

    Тогда итог, что языки с сборщиком мусора, под в 2 раза медленнее должны быть.(помимо сборки)

    Вот тут интереснее. Есть несколько хаков как достигается большая производительность.
    1. Линеризованное пространство памяти.
    Адреса 0, 1 и 2 поколения расположены не абы где, а последовательно, друг за другом. Т.е. если нужно сократить пространство 0 поколения, то это означает простое передвигание указателя влево.

    2. Переход в след. поколение происходит не всегда
    Из 0 в 1 - переход быстрый, но из 1 в 2 - не всегда.
    На этом этапе тоже может не затрачиваться много времени.

    3. Ссылки из недостижимых объектов не обновляются - эти объекты и так нигде не участвуют
    Обновление ссылок, к сожалению, - это ручное изменение и копирование. Ничего не поделаешь.

    Теперь где-то, сборщик мусора, начинает переносить arr в другое место.

    Ты слишком большой массив выделил, он аллоцируется в LOH. Оттуда не вытащишь.

    Я много о чем не упомянул. Например, очередь финализации, таблица дескрипторов (Handle), сегментирование памяти и т.д. но ответы на основные вопросы дал
    Ответ написан
    2 комментария
  • Как написать на с++ метод и экспортировать его в c# заинлайнить, и можно ли _fastcall его сделать???

    Nipheris
    @Nipheris Куратор тега C++
    Экспортированная функция работает в 4 раза медленнее.

    Разумеется, у вас всё время уходит на накладные расходы на PInvoke. Это полное безумие - выносить сложение чисел вообще в функцию, а тем более ещё и делать вызовом между языками. А PInvoke - это вам не InternalCall

    ВОПРОС как сделать функцию sum в с++ что бы она работала так же быстро как и sum в c# коде? Как ее заинлайнить

    Методы Math реализованы в самом рантайме и вызываются без маршалинга с помощью InternalCall. Не думаю, что это возможно для вашей функции.

    К примеру, если хочу c# библиотеку сделать, то просто добавили ссылку и забыл о всем. А когда добавляю так же ссылку на dll от с++ проекта, то ноль реакции.

    Потому что dll которые получились из C# - это дотнетовские сборки, которые только прикидываются Portable Executable, а вот то, что компилится из C++ - это действительно Portable Executable, и ничего дотнетовского там нет (если конечно это обычный C++ DLL-проект, а не C++/CLI).

    Кстати еще вопрос, как библиотеку с++ подключать к проекту, почему DllImport не находит, если указать ссылку на проект,

    Вам нужно настроить копирование C++ DLL в выходную директорию проекта, рядом с вашей дотнет-сборкой, в которой находится DllImport
    Ответ написан
    Комментировать
  • Как Jit Компиляторы обнаружат недостижимой код и лишние проверки?

    mayton2019
    @mayton2019
    Bigdata Engineer
    Как Jit Компиляторы обнаружат недостижимой код и лишние проверки?

    Если мне не изменяет память, JIT компиллятор компилирует java-метод целиком. Переводя byte-code в машинный код для x86 например.

    А то что спрашивает автор - это задача основного компиллятора который язык Java переводит в байткод.

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

    ли Космические Лучи, в Ram попали, что тогда будет?

    Программисты 20-го века работали в условиях глючной памяти (когда были ЭВМ на лампах и на тразнисторах)
    и обрабатывали специальное прерывание типа "глюк в ячейке памяти".

    С точки зрения современной парадигмы разработки - это невозможно. Никакой прикладной
    программист не ставит себе задачу отслеживания целостности памяти. Это как-бы не его
    уровень. Мы предполагаем что память надежна и всегда корректна. А иначе ОС выпадает
    в синий экран и никаких принятий решения мы все равно не сделаем а облачные балансировщики
    примут свои решения когда хост выпадет из сети.

    В современной ОС также по дефолту считается что никакой хакер никогда не меняет
    память вашего процесса. Это - основа безопасности ОС и если хакер все таки что-то может
    менять - то это плохая ОС и плохая безопасность и надо что-то решать на уровне системной
    архитектуры и тем более прикладной программист здесь ничего не сможет сделать.

    Рассматривать такие случаи в топике Java - бесполезно и контр-продуктивно. Давайте
    их рассматривать в топиках инфо-беза и операционок.
    Ответ написан
    Комментировать
  • IL генерация кода. Как загрузить в локальную переменную, константную ссылку на объект?

    VoidVolker
    @VoidVolker Куратор тега C#
    Dark side eye. А у нас печеньки! А у вас?
    Во-первых, рекомендую заюзать GrEmit - отличная либа для работы с ассемблером .Net.
    А во-вторых, есть такая замечательная штука под названием "дизассемблер": ildasm. Пишите обычный код на C#, разбираете его дизассемблером и смотрите что, куда и как, а потом уже пишите свой код аналогично.
    Ответ написан
    8 комментариев
  • Откуда stackoverflow при работе с stackalloc c#?

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    Похоже (явного указания в документации я не нашел), что память в стеке освобождается только при выходе из всего метода, но не из блока внутри него. Освобождение памяти в стеке, как известно - это сдвиг указателя стека обратно, и похоже, этого в конце блока не происходит - только в конце метода. Косвенное подтверждение - в документации по stackalloc явно написано избегать вызовов stackalloc в цикле, как это у вас сделано: "Avoid using stackalloc inside loops. Allocate the memory block outside a loop and reuse it inside the loop." ( https://learn.microsoft.com/en-us/dotnet/csharp/la... )
    Ответ написан
    Комментировать
  • Как эмуляторы транслируют клиентский код в машинный?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Когда эмулятор собирает и компилирует код jit, то как он этот код в машинных инструкциях составляет.

    Если ты посмотришь на QEMU, то у него есть фронт-енды (https://github.com/qemu/qemu/tree/v8.1.0/target), каждый из которых транслирует инструкции эмулируемой машины в промежуточный код. И есть бэк-енды (https://github.com/qemu/qemu/tree/v8.1.0/tcg), каждый из которых транслирует инструкции промежуточного кода в инструкции хостовой машины. Каждая гостевая инструкция может превратиться во множество промежуточных, а каждая промежуточная -- во множество хостовых. У разработчиков есть правило, что если на гостевую инструкцию требуется больше 20 промежуточных, то вместо прямой трансляции такая инструкция реализуется как вызов функции на C. Инструкции транслируются базовыми блоками, с заданного адреса и до достижения одного из следующих условий: 1) встречена инструкция выполняющая переход (условный или безусловный, вызов функции, возврат из функции, сюда же относятся инструкции гарантированно вызывающие исключение), или 2) PC переходит через границу страницы виртуальной памяти, или 3) количество инструкций в базовом блоке превышает заданный предел. Вдобавок с каждым оттранслированным базовым блоком ассоциируется дополнительный набор флагов, определяемый фронт-ендом, который кодирует состояние, в котором была машина при трансляции этого кода. Это позволяет иметь несколько вариантов трансляции для кода начинающегося с одного и того же адреса, например для разных уровней привилегий. Оттранслированные базовые блоки помещаются в кеш с функцией поиска по комбинации адреса и дополнительного набора флагов. В цикле выполнения эмулятор ищет транслированный базовый блок кода в кеше (а если не находит его, то транслирует и помещает в кеш), запускает его и получает контроль после завершения его выполнения.

    надо к примеру Перед выполнением каждой инструкции проверять наличие прерывания

    Вовсе не каждой, даже в 100% точной эмуляции нужно проверять IRQ только когда прерывания разрешены. QEMU обычно проверяет запрос на прерывание только перед входом в оттранслированный базовый блок.

    Или же есть несколько блоков, где линейно выполняется весь блок, а последняя инструкция прыгнет в другой блок.

    Да, QEMU выполняет трансляцию базовыми блоками.

    к примеру для вот такого примера графа, сколько базовых блоков можно построить?

    В этом графе не обозначены безусловные переходы, если их нет, то QEMU мог бы выделить такие базовые блоки: 0-1-2-3, 4-5-6, 7-8-1-2-3, 9-10, 11-12-13, 14-15-16-2-3, 17, всего 7 блоков.
    Если безусловные переходы -- это все переходы от узлов с бОльшими номерами к узлам с меньшими, то картина была бы такой: 0-1-2-3, 4-5-6, 7-8, 1-2-3, 9-10, 11-12-13, 14-15-16, 2-3, 17. Да, фрагмент 2-3 оттранслирован три раза: сам по себе и в составе других блоков.
    Ответ написан
    2 комментария
  • Ассемблер, почему дизассемблированном коде много ненужных операций?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Почему не переписать вместо этого
    add ebx,dword ptr [rbp+ECX*4+10h]

    Буквально так написать нельзя, потому что нет такого режима адресации в котором можно было бы использовать вместе Rbp (64-битный) и Ecx (32-битный). Можно было бы написать add ebx,dword ptr [rbp+rcx*4+10h], но для этого счётчик цикла должен был бы быть 64-битным, а он, как мы видим, 32-битный (int i). Т.е. ответ на вопрос "для чего это": для беззнакового расширения 32-битного счётчика цикла в регистр, который можно использовать для доступа к памяти.

    Другое дело, что из исходного кода очевидно, что при обращениях к памяти i не выходит из диапазона 0..9, так что разницы между ecx и rcx нет и не может быть. Возможно я что-то упускаю и у компилятора другое мнение на этот счёт, но может быть он просто туповат и не имеет кода который бы мог использовать эту возможность оптимизации, а может такая оптимизация и есть, но она не была включена во время генерации этого кода.
    Ответ написан
    Комментировать
  • Как написать на с++ метод и экспортировать его в c# заинлайнить, и можно ли _fastcall его сделать???


    Или бессмысленно маленькие методы экспортировать?

    Бессмысленно. Лучше сразу на C# их и писать.
    Прибегать к C++ и p/invoke есть смысл только если невозможно переписать на C#.

    Например это имеет смысл в случае библиотек уровня ffmpeg, sqlite, tensorflow
    Ответ написан
    Комментировать
  • Почему MouseMove не срабатывает?

    WNeZRoS
    @WNeZRoS
    У Canvas по умолчанию нет фона, соответственно курсору не за что зацепиться и MouseMove уходит окну. Если добавить для канваса Background="Transparent" (прозрачный цвет считается за фон, но визуально ничего не меняет), то всё будет работать.
    Раньше работало видимо потому что в канвасе были визуально видимые элементы.
    Ответ написан
    1 комментарий
  • Как к поймать событие OnMouseLeftButtonUp из пользовательского элемента UIElement?

    WNeZRoS
    @WNeZRoS
    Чтобы ловить события мыши вне элемента этот элемент должен захватить мышь через Mouse.Capture. Захват надо не забыть отменить когда он уже не актуален, иначе другие элементы не смогут получать события мыши.
    Ответ написан
    Комментировать
  • Как в wpf mvvc отобразить список элементов динамически?

    WNeZRoS
    @WNeZRoS
    Со структурой как у вас не понятно как оно должно работать.
    Если сделать ItemData типизированными, то всё становится проще - wpf может по типу выбирать подходящий DataTemplate, и значения мы получаем нужного типа, а не пойми что.

    public class SettingViewHost
    {
        public IReadOnlyCollection<SettingView>? Views { get; init; }
    }
    
    public class SettingView
    {
        public string? Name { get; init; }
        public IReadOnlyCollection<ItemData>? Options { get; init; }
    }
    
    public class ItemData
    {
        public string? Name { get; init; }
        public int GridRow { get; init; }
        public int GridColumn { get; init; }
    }
    
    public class BooleanItemData : ItemData // TODO implement INotifyPropertyChanged and raise PropertyChanged in Value setter
    {
        public bool Value { get; set; }
    }
    
    public class StringItemData : ItemData // TODO implement INotifyPropertyChanged and raise PropertyChanged in Value setter
    {
        public string Value { get; set; } = string.Empty;
    }


    Собираем SettingViewHost с любым количеством SettingView с разными внутренними настройками и закидываем во вью с такими шаблонами:

    <DataTemplate DataType="{x:Type local:StringItemData}">
        <StackPanel Orientation="Vertical">
            <TextBlock Text="{Binding Name, Mode=OneTime}" />
            <TextBox Text="{Binding Value}" />
        </StackPanel>
    </DataTemplate>
    
    <DataTemplate DataType="{x:Type local:BooleanItemData}">
        <CheckBox Content="{Binding Name, Mode=OneTime}" IsChecked="{Binding Value}" />
    </DataTemplate>
    
    <DataTemplate DataType="{x:Type local:SettingView}">
        <ItemsControl ItemsSource="{Binding Options}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <Grid IsItemsHost="True">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition />
                            <ColumnDefinition />
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition />
                            <RowDefinition />
                        </Grid.RowDefinitions>
                    </Grid>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemContainerStyle>
                <Style TargetType="{x:Type ContentPresenter}">
                    <Setter Property="Grid.Column" Value="{Binding GridColumn, Mode=OneTime}" />
                    <Setter Property="Grid.Row" Value="{Binding GridRow, Mode=OneTime}" />
                    <Setter Property="Margin" Value="4" />
                </Style>
            </ItemsControl.ItemContainerStyle>
        </ItemsControl>
    </DataTemplate>
    
    <DataTemplate DataType="{x:Type local:SettingViewHost}">
        <StackPanel Orientation="Vertical">
            <ComboBox Name="ComboBox" ItemsSource="{Binding Views}">
                <ComboBox.ItemTemplate>
                    <DataTemplate DataType="{x:Type local:SettingView}">
                        <TextBlock Text="{Binding Name, Mode=OneTime}" />
                    </DataTemplate>
                </ComboBox.ItemTemplate>
            </ComboBox>
            
            <ContentControl Content="{Binding ElementName=ComboBox, Path=SelectedItem}" />
        </StackPanel>
    </DataTemplate>


    Пример сделан с Grid'ом 2х2, можно использовать любую панель. Обычный Grid для динамических целей не удобен т.к. у него фиксированное кол-во строк и столбцов. Лучше использовать UniformGrid или что-то ещё, или развлекаться с attached dependency property или MarkupExtension чтобы динамически генерировать строки и столбцы.
    Ответ написан
    Комментировать
  • Как сделать преобразование фурье для изображения по xy?

    mayton2019
    @mayton2019
    Bigdata Engineer
    Что надо делать.?
    Не понимаю, с чего начать.

    Вообще если у тебя так много непоняток - то начни не с изображений а с 1-мерного графика.
    Курс валют например. Или ход температуры за сезон. Разберешся - дальше пойдешь.
    А если ты сейчас даже какую-то фигню закодишь
    - то как ты проверишь что правильное преобразование сделал?

    Начни с контракта. Что приходит тебе на вход? Вот это вот
    double[] x, double[]y

    С моей точки зрения - тут должна быть картинка. Image. На следующем уровне ты ее разбиваешь
    на цветовые слои. Красный зеленый ит.д. Потом эти слои разбиваешь на фреймы (8х8 пикс как в jpg).
    Потом их нормируешь от цвета пиксела до вещественного значения. И вот уже когда ты получишь
    матрицу вещественных значений - тогда и можно приступать к Фурье. Усек? У тебя хедер
    функции должен иметь такие параметры чтобы тебе было все кристально ясно что за аргументы и как.

    А так конешно у тебя каша в голове.

    Да. И по контракту Фурье преобразования ты получаешь комплесную
    вещественную матрицу на выходе. Тоесть две матрицы. Размер их не обязательно должен быть 8х8.
    Он может быть любым. Но обычно нижние коэффициенты матрицы (левый верхний угол - самые
    ценные для Фурье формулы).

    И дальше - делаешь все в обратном направлении. От Фурье к картинке. Получиться картинка - молодец.
    Значит правильно сделал.
    Ответ написан
    5 комментариев
  • Как в логике mvvc wpf передать в класс ViewModel из view свойство класса .xaml.cs?

    WNeZRoS
    @WNeZRoS
    Почему это поле не передается через, передается null
    CommandParameter="{Binding ElementName=selfUserControl,Path=Points, Mode=OneWay}">, selfUserControl x:Name элемента.

    Проперти Points должен быть public

    Находил примеры, там везде свойство ItemsSource, но такого свойства нету у Canvas

    Надо использовать ItemsControl, у которого как раз есть ItemsSource, а Canvas использовать как панель для этого ItemsControl через ItemsPanel
    Ответ написан
    Комментировать
  • Как в логике mvvc wpf передать в класс ViewModel из view свойство класса .xaml.cs?

    @SZolotov
    Asp.net core, MAUI,WPF,Qt, Avalonia
    Почему это поле не передается через, передается null
    CommandParameter="{Binding ElementName=selfUserControl,Path=Points, Mode=OneWay}">


    Потому что свойство которое биндится должно быть dependency property
    Плюс почитайте про отличие List от ObservableCollection, что за чем нужно и когда использовать первое и второе применительно к биндингам. Потом зачем нужен интерфейс INotifyPropertyChanged
    Ну и коллекцию кидать как параметр команды такое себе решение.
    Ответ написан
    Комментировать
  • Какими соседями будут граничные клетки на замкнутой поверхности?

    Alexandroppolus
    @Alexandroppolus
    кодир
    соседи для элемента a[x, y] в табличке размером W по горизонтали и H по вертикали (индексы с нуля)

    сверху: a[x, (y + H - 1) % H]
    снизу: a[x, (y + 1) % H]
    слева: a[(x + W - 1) % W, y]
    справа: a[(x + 1) % W, y]

    a % b - остаток от деления a на b
    Ответ написан
    Комментировать
  • Какими соседями будут граничные клетки на замкнутой поверхности?

    hint000
    @hint000
    у админа три руки
    a03 слева
    a30 сверху
    a33, a13 и a31 по диагоналям
    Это если поверхность топологически эквивалентна сфере тору (см. комментарии). Но ведь можно и другим способом замкнуть, хотя это уже будет посложнее.

    для общности можно всегда от индексов брать остаток от деления, тогда:
    a((x-1)mod m,(y-1)mod n)  a(x mod m,(y-1)mod n)  a((x+1)mod m,(y-1)mod n)
    a((x-1)mod m, y   mod n)  a(x,y)                 a((x+1)mod m, y   mod n)
    a((x-1)mod m,(y+1)mod n)  a(x mod m,(y+1)mod n)  a((x+1)mod m,(y+1)mod n)
    Ответ написан
    4 комментария