Задать вопрос
  • Стоит ли вынести объявление типов в отдельный файл?

    @Mercury13
    Программист на «си с крестами» и не только
    Стоит!
    Назовите этот хедер как-нибудь defines.h
    Ответ написан
    Комментировать
  • Как взять данные stringstream без копирования?

    @Mercury13
    Программист на «си с крестами» и не только
    stringstream не обязан хранить данные в строке. Так что функция str() просто собирает информацию в строку.

    https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++...

    Судя по исходникам G++, их sstream хранит информацию в длинном буфере, но не в строке. Но и это не обязательно; буферов может быть много.

    Так что, к сожалению, для экономии памяти придётся делать свой велосипед. Правда, как говорит MiiNiPaa, некоторые задачи удастся выполнить и на stringstream’е, воспользовавшись, например, итератором.
    Ответ написан
    Комментировать
  • Как сделать скриншот определенной программы на java?

    @Mercury13
    Программист на «си с крестами» и не только
    colororacle.org
    Вот тут опенсорсный симулятор дальтонизма на Java. Делает снимки всего экрана; как — посмотрите в исходники.

    Сомнительно, что получится на Java кроссплатформенно сделать снимок отдельной программы — больно уж системная штука.

    P.S. Для скриншотов используется класс, именуемый «тестирующий робот» — скриншот-то им можно сделать, а вот как получить прямоугольник чужого окна? По-видимому, только через native-обёртку.

    P.P.S. Оказывается, и native-обёртка есть — JNA. С ней никогда не работал.
    Ответ написан
    Комментировать
  • Как overcockers узнают про правленный hosts?

    @Mercury13
    Программист на «си с крестами» и не только
    Ещё и с ошибкой написали, правильно «правленый».

    А вот так. Из кода страницы.
    var script = document.createElement('script');
    script.onerror = function(){
       // тут пишем сообщение об ошибке
    }
    script.src = "https://c.amazon-adsystem.com/aax2/amzn_ads.js";
    document.body.appendChild(script);

    То есть всё просто: если при вызове рекламы произошла ошибка, выводим сообщение.

    Вот гады ползучие, очередной сайт, написанный полностью на JS и ничего не выводящий, когда такового нет.

    Да ещё и опечатка у вас под стать этому гадству: «overcockers».
    Ответ написан
    Комментировать
  • Для чего нужны замыкания в C++ и как вы их используете?

    @Mercury13
    Программист на «си с крестами» и не только
    Замыкание — это способ передать в callback, из какого контекста он запустился.
    struct Row {
      int data[10];
    };
    struct Table {
      Row rows[10];
    }

    Нам нужно отсортировать таблицу по j-му столбцу. Номер j заранее неизвестен.

    int sortJ;
    
    int myCompare(const void* a,const void* b) {
      int ia = reinterpret_cast<Row*>(a)->data[sortJ];
      int ib = reinterpret_cast<Row*>(b)->data[sortJ];
      if (ia < ib) return -1;
      if (ia == ib) return 0;
      return 1;
    }
    
    int someJ = 5;
    sortJ = someJ;
    qsort(table.rows, 10, sizeof(Row), myCompare);

    Вот эта переменная sortJ — по какому столбцу сортировать — это и есть замыкание. Но, как известно, «избегай незнакомых женщин и глобальных переменных». Поэтому на STL мы делаем функтор (объект-функцию) и эту информацию кидаем в него.

    class MyCompare {
    public:
      MyCompare(int aJ) : j(aJ) {}
      bool operator () (const Row& a, const Row& b) const
        { return (a.data[j] < b.data[j]); }
    private:
      const int j;
    }
    
    int someJ = 5;
    std::sort(table.rows, table.rows + 10, MyCompare(someJ));

    Вот мы и избавились от глобальной переменной, закинув наше замыкание в private-поля объекта.

    Что плохо? Не будем говорить про технические тонкости. С точки зрения красоты и лаконичности кода: код слишком разлапистый. И тут пришёл C++11.
    int someJ = 5;
    std::sort(table.rows, table.rows + 10,
      [someJ](const Row& a, const Row& b) -> bool { return (a.data[someJ] < b.data[someJ]); } );

    Корявовато, но таков синтаксис Си++. Автоматически создаётся объект-функтор, и someJ становится его полем. Вот оно, замыкание — [someJ] — то есть те вещи, которые надо протащить внутрь функтора.

    Из реального проекта. Отбегал поток автоматического поиска нового регистрационного ключа; если что-то получилось — синхронно вызываем лямбду через Qt’шный механизм «сигнал-слот». Чтобы всё было синхронно, нужен объект, живущий в главном потоке (и он в интерфейсе MainControl — управление главной формой — тоже есть). Но тогда придётся вызывать не слот, а лямбду. Этой лямбде нужны два поля: fReregKey (новый ключ защиты от копирования) и fMainControl. Оба они в this, его и замыкаем.
    connect(this, &RenewThread::needUpdate, fMainControl.maincQobj(),
                [this]() {
            drm::createFile(fReregKey);
            fMainControl.maincLayoutOnRegister();
        });


    А теперь посмотрим в WinApi. Первая попавшаяся функция из DirectInput.
    HRESULT EnumObjects(
             LPDIENUMDEVICEOBJECTSCALLBACK lpCallback,
             LPVOID pvRef,
             DWORD dwFlags
    );
    
    BOOL DIEnumDeviceObjectsCallback(
             LPCDIDEVICEOBJECTINSTANCE lpddoi,
             LPVOID pvRef
    );

    Про pvRef говорится: функции EnumObjects он ни на что не нужен; что функция приняла, то и даст в callback. Тоже форма замыкания: можно передать указатель на любые данные, которые нужны callback’у.
    Ответ написан
    4 комментария
  • Почему ошибка в netbeans c++?

    @Mercury13
    Программист на «си с крестами» и не только
    В одном проекте два CPP-файла: int_float.cpp и hello.cpp. В обоих по main’у.
    Я не знаю, как NB объединяет файлы в проект, но если всё, что в каталоге и подкаталогах — значит, не держи где-то в подкаталогах другой проект.

    Второй вариант — очистить временный каталог с .o-файлами; там, возможно, завалялось что-то старое.
    Ответ написан
    Комментировать
  • Как определить число инверсий для перестановки?

    @Mercury13
    Программист на «си с крестами» и не только
    Инверсия — это когда a < b, но стоят они наоборот.
    В пределах блока (например, 1…3n−2) инверсий, разумеется, нет.

    Между первым и вторым блоком.
    • С 2-кой: 4, 7,… То есть n−1 шт.
    • С 5-кой: начиная с 7 — то есть n−2 шт.
    • Итого 0 + 1 + 2 +…+ (n−1) = n(n−1)/2 шт.

    Между первым и третьим, и между вторым и третьим сам инверсии посчитаешь? И чётное оно или нет — тоже, надеюсь, посчитать несложно.
    Ответ написан
    Комментировать
  • Как разнести класс по файлам?

    @Mercury13
    Программист на «си с крестами» и не только
    Принцип прост. В .h можно ставить только то, что не производит кода. Как только в проекте появится второй CPP и задействует этот хедер, код будет произведён дважды, и компоновщик (cl/ld/ilink) будет ругаться, что переменная или функция в двух экземплярах. Что именно не производит кода…
    • Определения макросов. Они в принципе кода не производят.
    • Объявление любого типа. Оно лишь говорит об устройстве этого самого типа; код же производят те, кто этим типом пользуются.
    • Шаблоны. Код производит не сам шаблон, а факт расшаблонивания. Разумеется, шаблон может расшаблониться в двух единицах компиляции, но с этим автоматически бороться научились.
    • inline—  код производит не сам inline, а факт включения. inline бывает как явный ключевым словом, так и неявный — в теле класса.
    • Прототипы и extern — они говорят: код есть, но где-то не здесь.
    • Constexpr C++11. Они подставляют значение.
    • Некоторые const в зависимости от компилятора. Например, на Borland const double производит код, а const int — нет.

    Производят код и в хедерах запрещены.
    • Переменная без extern, даже const.
    • Функция, которая не inline.
    • Полностью специализированный шаблон, в котором не осталось шаблонных параметров (template<>).

    Не производят кода, но и лучше закинуть в CPP.
    • Некоторые скрытые (private) inline и шаблоны, если они не используются из хедера.
    Ответ написан
    3 комментария
  • Как изменить класс компонента?

    @Mercury13
    Программист на «си с крестами» и не только
    Самый простой способ. Открываем DFM (ПКМ на форме, View as Text) и проводим Search-Replace.
    После этого вносим любые изменения в модуль (да хоть пробел добавляем и удаляем), и сохраняем. Автоматика будет спрашивать: заменить? — соглашаемся.

    Я изменял в Unit1.pas - type TPanel на sPanel и в Unit1.dfm TPanel на sPanel.
    Но при открытии пишет, что класс sPanel не найден, хотя в uses прописано sPanel.

    Если модуль называется sPanel, то сам компонент должен немного по-другому. TsPanel?

    UPD. Да, TsPanel, если это он.
    Ответ написан
    Комментировать
  • Как можно реализовать?

    @Mercury13
    Программист на «си с крестами» и не только
    Подсчитать кол-во нулей (единиц, двоек, троек). Если неодинаково — нельзя.
    Иначе — подсчитаем такую матрицу (4×4). Если в 1-й строке на i-м месте 1, а во 2-й 3, прибавляем единицу к a[1, 3].
    a[i, i] не учитываем: они уже на своих местах.
    a[i, j] и a[j, i] взаимокоменсируем: каждая такая парочка даёт min(a[i, j], a[j, i]) перестановок.
    Точно так же пересматриваем все тройки a[i, j], a[j, k] и a[k, i]. Как всегда, взаимокомпенсируем их; каждая такая тройка даёт 2·min(•, •, •) пререстановок.
    Остаётся просуммировать всё, что осталось (кроме диагонали, разумеется), и помножить на 3/4.
    Ответ написан
    Комментировать
  • На чем сейчас разрабатывают игры?

    @Mercury13
    Программист на «си с крестами» и не только
    Почему скриптовой язык идет вместе с компилируемыми? Разные задачи?

    1. Для упрощения внутренней логики игры. Например, программа — монолитное однопоточное приложение, но каждый объект ведёт себя как сопрограмма. Качающийся маятник можно реализовать на состоянии и на сопрограммах…
    // На состоянии
    функ Маятник.ПровестиТакт
      ++кадр;
      если (кадр >= 10)
        кадр = 0;
      УстановитьКадр(кадр);
    
    // На сопрограммах
    функ Маятник.Жизнь
      для i=[0..10)
        УстановитьКадр(i)
        НовыйТакт


    2. Чтобы геймдизайнеры и прочие непрофессионалы (в программировании, естественно, непрофессионалы) могли свободно корректировать код.

    3. Часто игру пишут на готовом движке. А в нём зашит какой-то скриптовый язык — это самый простой способ написать игровой движок, законченный и пригодный к применению программистом куда меньшей квалификации. Так, например, устроен Wintermute Engine (старый, но хорошо известный движок для квестов).

    Читал, что плюса, C#, Lua.

    • C++: язык с давними традициями в геймдеве. Выразительный код (при достаточном профессионализме) плюс контроль за деструкторами — так что не будет просадок FPS из-за мусорщика. Выбор №1, если нужно написать игру с нуля.
    • C#: очень простой в изучении язык общего назначения. Библиотеки для Windows, скорее всего, у пользователя есть изначально. Куча движков, библиотек и фреймворков. Даром, что мусорный — если игра не слишком сложная, просадок FPS не будет (хотя последнего босса Hyper Light Drifter я долго громил — в критические моменты игра тормозила).
    • Lua: наиболее известный из скриптовых языков, которые можно реально присоединять к Си-программе, и скрипт будет вызывать функции, написанные на обычном компилируемом языке.
    Ответ написан
    Комментировать
  • Как правильно организовать структуру в классе?

    @Mercury13
    Программист на «си с крестами» и не только
    Помимо того, что я написал…

    1. Как устроить данные?
    struct CheckLine {
    public:
       int itemCode;    // код товара
       int qty;         // количество
       int price;       // цена, по которой всё это продано в копейках
       const CheckLine* next() const { return _next; }
    private:
       friend class Check;   // я тут ошибся с const-корректностью и заconst’ив всё, что можно, не дал Check’у писать
       CheckLine* _next;
    }
    
    class Check {
    public:
        Check() : _firstLine(NULL), _lastLine(NULL) {}
        void addLine(int itemCode, int qty, int price);   // пиши реализацию сам.
        const CheckLine* firstLine() const { return _firstLine; }
        ~Check();  // не забудь про деструктор…
        Check(const Check&)  // …конструктор копирования…
        Check& operator = (const Check&);  // и операцию «присвоить».
    private:
        CheckLine *_firstLine, *_lastLine;
    }

    В общем, я тут для простоты (мы же пока не знаем, что такое vector) наладил хранение данных связанным списком.

    2. Во внутренней кухне класса ты обращаешься к консоли. Зачем? Обычно это делают как можно ближе к main.

    Вернусь — буду писать дальше.
    Ответ написан
    3 комментария
  • Как удалить файлы по маске в подкаталогах Delphi?

    @Mercury13
    Программист на «си с крестами» и не только
    Ну ясен перец.
    Каталоги надо искать по *, а файлы удалять по *.log.
    Ответ написан
    Комментировать
  • Как расставить скобки в выражении всеми возможными способами? какова сложность оптимального алгоритма?

    @Mercury13
    Программист на «си с крестами» и не только
    Тут чёткое динамическое программирование. У нас N+1 операнд, и N операций.
    Создаём кэш: для всех L и R, 0<=L<=R<=N, мы храним:
    • Операцию: null, +, ×, many.
    • Ассоциативный массив:
    •• Ключ — число (целое/рациональное/плавающее/фиксированное — с какими хотите работать).
    ̃•• Значение — тройка:
    ••• Номер операции с макс. приоритетом.
    ••• Значение слева (такое же число).
    ••• Значение справа (такое же число).
    Для всех L=R кэш заполнен такой величиной:
    • Операция — null.
    • В массиве один элемент: ключ — операнд, значение — любая затычка.
    Для кэша годится, например, матрица (N+1)×(N+1).

    После этого проходимся по диагоналям нашего кэша, обрабатывая сначала L=0..N−1, R=L+1, затем L=0..N−2, R=L+2, и т.д., пока на дойдём до диагонали из одного элемента: L=0, R=N. Как именно обрабатываем?
    1. Смотрим операцию, записанную в кэше (L+1, R), и L-ю операцию в выражении. Если вторая — «сложить» или «умножить», а первая — null или совпадает, записываем эту операцию в кэш на место (L, R). Иначе — пишем many.
    2. Вычисляем R1: если в кэше на месте (L, R) есть какая-то операция, то L; если many — то R−1 (оптимизация по ассоциативности).
    3. Проходимся по всем M=L…R1.
    3.1. Двойным циклом проходимся по содержимому кэша в (L,M) и (M+1, R). Обозначим переменные u и v.
    3.1.1. Записываем в кэш на место (L,R), если таковое отсутствует:
           • ключ u (+−×/) v
           • номер операции — M
           • значения слева и справа — u и v.
    Рассмотрим, например 1 + 2 + 3 − 4.
    (0, 0) — null; (1 → ? ? ?)
    (1, 1) — null, (2 → ? ? ?)
    (2, 2) — null, (3 → ? ? ?)
    (3, 3) — null, (4 → ? ? ?)

    UPD: Операнды у наc { 1 2 3 4 }, орерации { + + − }. Ну разумеется.

    Теперь смотрим, что будет в (0, 1). В (1, 1) в кэше null, нулевая операция + — операция +. Одна итерация, R1=0.
    Прокрутив эту итерацию, получаем…
    (0, 1) — +; (3 → 0 1 2). Это означает: получили 3, сложив 0-м плюсом 1 и 2.
    Аналогично…
    (1, 2) — +; (5 → 1 2 3)
    (2, 3) — many; (−1 → 2 3 4)

    Вторая диагональ. (0, 2). В позиции (1, 2): в кэше +, 0-я операция +. Записываем + и прокручиваем одну итерацию, от 0 до 0. Т.е. складываем (0, 0) и (1, 2).
    (0, 2) — +; (6 → 0 1 5).
    Теперь (1, 3). Операция будет many; прокручиваем и получаем:
    для M=1 — складываем (1, 1) и (2, 3), и получаем (1 → 1, 2, −1).
    для M=2 — вычитаем (1, 2) и (3, 3), и получаем (1 → 2, 5, 4).
    Если без дублей…
    (1,3) — many; (1 → 1 2 -1)

    Ну и, наконец, пошли (0, 3). Операция будет many…
    для M=0 — складываем (0, 0) и (1, 3), и будет (2 → 0 1 1).
    для M=1 — складываем (0, 1) и (2, 3), и будет (2 → 1 3 −1).
    для M=2 — вычитаем (0, 2) и (3, 3), и будет (2 → 2 6 −4). Повторим, что это значит: получилось 2, из-за того, что вычли 2-м минусом 6 и −4.
    Итого, без дублей, (0, 3) — many, (2 → 0 1 1).

    Так «повезло», что у нас вышел один результат. Но в результате объединения может быть и множество.

    А теперь вопрос: откуда мы получили 2-ку? Смотрим в (0, 3) и получаем: 2 = 1 +0 1. Левую единицу раскрываем через (0, 0), правую — через (1, 3): 2 = 1 +0 2 +1 (−1).
    Остаётся раскрыть −1, и получаем 2 = 1 + 2 + 3 − 4.
    Это можно сделать рекурсивно.

    Если точный путь вычислений не нужен, ассоциативный массив превращается в множество без повторов. Не (2 → 0 1 1), а просто 2.
    Во многих вариантах динамического программирования, если прямой ход не нужен, двухмерный кэш можно превратить в одномерный. Тут я не вижу способа. Написал, да понял, что ошибся.

    UPD. А сложность какая? — у меня выходит 2n·n². Почти уверен, что реально цифра меньше, просто думать над этим облом.
    Ответ написан
    Комментировать
  • Your CPU does not support required features (VT-x or SVM)?

    @Mercury13
    Программист на «си с крестами» и не только
    Ну очевидно.
    Если у вас Windows/OSX: либо использовать процессор Intel с функцией VT-x (виртуализация), либо выбрать из списка другой эмулятор (правда, медленно будет).
    Если у вас Linux — также годятся процессоры AMD с функцией SVM.
    Ну и, разумеется, можно заливать программу не на эмулятор, а на настоящий телефон.

    Процессор-то у вас какой? Вижу, требования жёсткие, и может случиться, что Hyper-V работает, а AS — нет.
    Ответ написан
  • Как решить уравнение х*х-2=3y в целых числах?

    @Mercury13
    Программист на «си с крестами» и не только
    x делится на 3: 9z² − 2 = 3y. Справа делится на 3, слева нет.
    Иначе: (x−1)(x+1) = 3y + 1. Хотя бы один из множителей кратен трём. Всё наоборот: слева делится на 3, справа нет.
    Дальше уже, по-моему, доказательство не упростить.
    Ответ написан
    Комментировать
  • Как правильно распределить память?

    @Mercury13
    Программист на «си с крестами» и не только
    Что у нас такое cur_dir?
    У функции strcat_s три параметра…
    errno_t strcat_s(
       char *strDestination,
       size_t numberOfElements,
       const char *strSource 
    );

    В C++ есть также шаблонная перегрузка с двумя параметрами.
    template <size_t size>
    errno_t strcat_s(
       char (&strDestination)[size],
       const char *strSource 
    ); // C++ only

    Вывод такой. Перегрузка с двумя параметрами принимает первым параметром только массив, но не char*.

    P.S. А лучше, конечно, будет использовать контейнеры наподобие std::string.
    Ответ написан
    3 комментария
  • Как объяснить кусок кода C++?

    @Mercury13
    Программист на «си с крестами» и не только
    Весь этот код (за исключением Close) — автогенерируемый.

    ///// Защита от повторного включения
    #ifndef Unit1H
    #define Unit1H
    
    ///// Хедеры VCL. Причём всё это сделано так, чтобы упростить написание ценой удлинения
    ///// компиляции. Более громоздкий, но и более удачный вариант.
    ///// В H:
    /////   namespace Controls { class TLabel; }
    /////   using namespace Controls;
    ///// В CPP:
    /////   #include <Controls.hpp>
    ///// Вот таким образом можно (было) избавиться от каскадного подключения
    ///// хедера Controls. А то каждый, кто использует главной форму,
    ///// автоматически подключает эти хедеры.
    #include <Classes.hpp>
    #include <Controls.hpp>
    #include <StdCtrls.hpp>
    ///// Только от Forms.hpp избавиться таким макаром нельзя:
    ///// мы наследуемся от TForm.
    #include <Forms.hpp>
    
    ///// Класс формы. Все формы наследуются от TForm.
    class TForm1 : public TForm
    {
       ///// Особое право доступа Borland, для совместимости с Delphi.
       ///// Поля и свойства published не просто public, но включаются
       ///// в структуру рефлексии (aka reflection или introspection)
       ///// и программа о них знает при выполнении.
       ///// Применительно к формам — published-поля доступны
       ///// загрузчику.
    __published: // IDE-managed Components
       ///// Компоненты, которые мы установили на форме редактором.
    TLabel *Label1;
    TButton *Button1;
       ///// События, которые мы прописали в редакторе.
       ///// __fastcall — модель вызова, аналогичная Delphi.
       ///// Именно такая модель вызова принята в обработчиках
       ///// событий.
    void __fastcall Button1Click(TObject *Sender);
       ///// Пользователь пока не прописал никаких своих
       ///// полей и функций.
    private: // User declarations
    public: // User declarations
       ///// Конструктор. Раз уж у формы нетривиальный конструктор —
       ///// по правилам Си++ его надо повторить в подклассе.
       ///// Снова-таки, модель вызова __fastcall: в формах Delphi
       ///// используются т.н. виртуальные конструкторы, 
       ///// когда по имени класса можно создать объект этого класса.
       ///// Фабричный метод, только немного лучше.
       ///// Но это значит: у всех подчинённых классов
       ///// должен быть один и тот же набор параметров
       ///// и модель вызова.
    __fastcall TForm1(TComponent* Owner);
    };
    //---------------------------------------------------------------------------
    ///// Как известно, переменная объявляется один раз.
    ///// Поскольку хедер может подключаться к огромному числу CPP,
    ///// её объявляют как extern (она есть, но в другом месте).
    ///// Макрос PACKAGE раскрывается в __declspec(package),
    ///// чтобы эту штуку можно было собрать как пакет.
    extern PACKAGE TForm1 *Form1;
    //---------------------------------------------------------------------------
    #endif

    Модель вызова — это как технически мы вызываем подпрограмму. Какая память и какие регистры на это используются, и кто подчищает стек. Ищи в Википедии.
    Ответ написан
    Комментировать
  • Насколько необходимы навыки художника для геймдизайнера?

    @Mercury13
    Программист на «си с крестами» и не только
    Нужно постольку, поскольку художник понимает ваши почеркушки. В смысле, какие-то знания не помешают, но не самоцель.
    Куда важнее (из художественного)…
    • Понимание стилей искусства, как исторических, так и современных.
    • Умение быстро сфотошопить концепт-рисунок, который и будет техзаданием художнику.
    • Умение внятно, словами и зарисовками, объяснить художнику, где он не прав.
    • По портфолио понять, брать художника в проект или не стоит.
    • Умение собрать из «всякого хлама в интернете» временную картинку, чтобы понять, не будет ли лучше другая метафора или другой стиль.

    Бывают игры, вышедшие из графического стиля. Например: Myst, Syberia, Transistor. В них геймдизайнер — в первую очередь художник. Но важно и сделать надлежащий геймплей — то, чего, по-моему, не хватает Transistor.
    Ответ написан
    Комментировать
  • Почему видеокарта работает только без драйверов?

    @Mercury13
    Программист на «си с крестами» и не только
    У видеоплаты очень много блоков, в том числе…
    • Графические конвейеры.
    • Видеопамять.
    • RAMDAC и его аналог, дающий интерфейс DVI.
    • Блок аппаратной отрисовки примитивов в 2D (не так быстро, как графическими конвейерами, но до пикселя точно).
    • Блок совместимости с VGA и VESA (это очень старые стандарты, но надо же как-то показывать, пока нет драйверов?)
    • Интерфейс PCI-Express, который и даёт взаимодействие видяхи с шиной.
    • Схема питания.
    Вариант 1. Слетел один или несколько видеоконвейеров; видяха работает только в совместимости с VESA, где видеоконвейеры не нужны.
    Вариант 2. Слетела часть памяти или её дешифратор; драйверы Microsoft и nVidia держат видеобуфер в разных местах.
    Вариант 3. Слетел один из преобразователей питания (у хорошей видяхи их может быть до 4). Какой-то простейший набор блоков работает, а переходим на полное ускорение — нет.
    Вариант 4. Слетела часть выводов PCI-Express, из-за чего в новом PCI-Express не получается раскочегарить видяху.

    Реальный случай. ThinkPad T-series — хорошие ноутбуки, но T40 известен своим ненадёжным Radeon Mobility. Чип отвалился и работал только в совместимости с VESA.
    Ответ написан
    1 комментарий