Горячее
Лучшее
Свежее
Подписки
Сообщества
Блоги
Эксперты
Войти
Забыли пароль?
или продолжите с
Создать аккаунт
Я хочу получать рассылки с лучшими постами за неделю
или
Восстановление пароля
Восстановление пароля
Получить код в Telegram
Войти с Яндекс ID Войти через VK ID
Создавая аккаунт, я соглашаюсь с правилами Пикабу и даю согласие на обработку персональных данных.
ПромокодыРаботаКурсыРекламаИгрыПополнение Steam
Пикабу Игры +1000 бесплатных онлайн игр
Добро пожаловать в Кран-ресторан — казуальный симулятор, который превратит вас в настоящего мастера кулинарии! Управляйте краном, ловите нужные ингредиенты и готовьте блюда по рецептам, избегая ошибок, чтобы сохранить рейтинг и получить ценные награды.

Кран-Ресторан

Казуальные, Аркады, Шарики

Играть

Топ прошлой недели

  • Rahlkan Rahlkan 1 пост
  • Tannhauser9 Tannhauser9 4 поста
  • alex.carrier alex.carrier 5 постов
Посмотреть весь топ

Лучшие посты недели

Рассылка Пикабу: отправляем самые рейтинговые материалы за 7 дней 🔥

Нажимая кнопку «Подписаться на рассылку», я соглашаюсь с Правилами Пикабу и даю согласие на обработку персональных данных.

Спасибо, что подписались!
Пожалуйста, проверьте почту 😊

Помощь Кодекс Пикабу Команда Пикабу Моб. приложение
Правила соцсети О рекомендациях О компании
Промокоды Биг Гик Промокоды Lamoda Промокоды МВидео Промокоды Яндекс Директ Промокоды Отелло Промокоды Aroma Butik Промокоды Яндекс Путешествия Постила Футбол сегодня
0 просмотренных постов скрыто
6
mcnikirikitiki
5 месяцев назад
Лига программистов

Основы C++: Ветвления, Циклы, Векторы и Строки⁠⁠

Прежде чем читать мою статью - реши для себя, зачем ты это делаешь. Даже если ты просто нормальный человек, лишним не будет.

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

Здравствуйте, мои маленькие любители программирования!

Сегодня мы разберем ключевые конструкции C++: ветвления , циклы , векторы и строки . Это как азбука программиста — без них никуда. Готовы? Погнали!


1. Ветвления: если «если», то идем дальше

В жизни мы постоянно принимаем решения: «Если дождь — возьми зонт», «Если голоден — поешь». В C++ для этого есть операторы if, else if, else и switch.

1.1. Оператор if

Простейший пример:

if (x > 0) {

std::cout << "Число положительное!\n";

} else {

std::cout << "Число не положительное...\n";

}

Важно:

  • Фигурные скобки {} можно не ставить, если внутри одна строка. Но лучше ставить всегда — так меньше ошибок.

  • Условия можно комбинировать через && (и), || (или), ! (не).

Пример сложного условия:

if ((age >= 18 && age <= 65) || hasSpecialPermission) {

// Условие читается как:

// "Если возраст от 18 до 65 ИЛИ есть специальное разрешение"

}

1.2. Оператор switch

Идеален для выбора из множества вариантов:

switch (operation) {

case '+':

result = a + b;

break;

case '-':

result = a - b;

break;

default:

result = 0; // если ни один case не подошел

}

Важно:

  • Не забудьте break, иначе выполнение «провалится» в следующий case.

  • switch работает только с целыми числами и символами. Со строками — нельзя!

1.3. goto — зло?

Да, его лучше не использовать. Но для примера:

again:

std::cout << "Введите возраст: ";

int age;

std::cin >> age;

if (age < 0) goto again; // прыжок на метку again

Совет: Вместо goto используйте циклы. Они читабельнее и безопаснее.


2. Циклы: повторяем, пока не надоест

Циклы нужны, чтобы выполнять код много раз. В C++ их три вида: while, do-while, for.

2.1. Цикл while

Проверяет условие перед итерацией:

int n = 1;

while (n <= 10) {

std::cout << n << " ";

++n;

}

// Вывод: 1 2 3 ... 10

2.2. Цикл for

Идеален для перебора элементов:

for (int i = 1; i <= 10; ++i) {

std::cout << i << " ";

}

Фишка: Можно использовать range-based for для контейнеров:

std::string line = "Hello";

for (char c : line) {

std::cout << c << " "; // H e l l o

}

2.3. break и continue

  • break — досрочный выход из цикла.

  • continue — переход к следующей итерации.

Пример:

while (true) {

int x;

std::cin >> x;

if (x == 0) break; // выход при вводе 0

if (x < 0) continue; // пропуск отрицательных

std::cout << x << " ";

}


3. Векторы: динамические массивы

std::vector — это массив, который умеет расти. Подключаем через <vector>.

3.1. Создание и доступ

std::vector<int> nums = {1, 2, 3};

nums.push_back(4); // добавляем 4 в конец

std::cout << nums[0]; // 1 (первый элемент)

std::cout << nums.size(); // 4 (размер вектора)

Важно:

  • Обращение по неверному индексу (nums[10]) — неопределенное поведение.

  • Используйте at() для проверки границ: nums.at(10) выбросит исключение.

3.2. Дополнительные методы

std::vector<int> v = {1, 2, 3};

v.empty(); // проверка на пустоту

v.clear(); // очистка вектора

v.reserve(100); // резервирование места для 100 элементов

v.capacity(); // текущая ёмкость

3.3. Сортировка вектора

#include <algorithm>

std::vector<int> data = {3, 1, 4};

std::sort(data.begin(), data.end()); // 1, 3, 4


4. Строки: не просто символы

std::string — это вектор символов с дополнительными функциями. Подключаем через <string>.

4.1. Основные операции

std::string s = "Hello";

s += " World!"; // "Hello World!"

std::cout << s.substr(6, 5); // "World" (подстрока)

size_t pos = s.find("World"); // позиция = 6

4.2. Дополнительные методы

std::string s = "Hello";

s.size(); // длина строки

s.empty(); // проверка на пустоту

s.append(" World"); // добавление

s.erase(0, 1); // удаление символа по индексу

s.replace(0, 5, "Hi"); // замена подстроки

s.find_first_of("aeiou"); // поиск первой гласной

4.3. Палиндром? Легко!

#include <algorithm>

std::string word = "радар";

std::string reversed = word;

std::reverse(reversed.begin(), reversed.end());

if (word == reversed) {

std::cout << "Это палиндром!\n";

}


Практика: 5 задач для закрепления

Задача 1: «Сумматор»

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

Введите числа: 5 3 -2 0

Сумма: 6

Задача 2: «Поиск максимума»

Описание: Создайте вектор из 10 случайных чисел (от 1 до 100). Найдите максимальный элемент. Подсказка: Используйте rand() % 100 + 1 для генерации чисел.

Задача 3: «Шифратор»

Описание: Напишите программу, которая заменяет все гласные буквы в строке на символ '*'. Пример:

Введите строку: Hello

Результат: H*ll*

Задача 4: «Калькулятор»

Описание: Реализуйте простой калькулятор, который принимает два числа и операцию (+, -, *, /). Используйте switch для обработки операций.

Задача 5: «Удаление пробелов»

Описание: Напишите программу, которая удаляет все пробелы из введенной строки. Пример:

Введите строку: Hello World

Результат: HelloWorld


Заключение

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

Показать полностью
[моё] Программирование Гайд C++ IT Длиннопост
2
7
mcnikirikitiki
5 месяцев назад
Лига программистов

Знакомство с C++⁠⁠

Прежде чем читать мою статью - реши для себя, зачем ты это делаешь. Даже если ты просто нормальный человек, лишним не будет.

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

Заранее благодарю за понимание.

Здравствуйте, мои маленькие любители программирования.

Итак, C++ — это язык, которому почти 40 лет. Да-да, он старше многих из вас! Но, как говорится, возраст — это просто число. C++ до сих пор остается актуальным и востребованным. Он был создан Бьярне Страуструпом (да благословит его каждый программист) как расширение языка C. Изначально он даже назывался "Си с классами". Но чтобы начать учить C++, совсем не обязательно знать C. Хотя, конечно, базовые знания программирования вам понадобятся. Например, можно быть знакомым с Python — этим милым, дружелюбным языком, который так любят в школах.

Но вот парадокс: C++ во многом полная противоположность Python. Если Python — это интерпретируемый язык, где вы пишете код и сразу видите результат, то C++ — компилируемый. Это значит, что перед запуском программы вам нужно скомпилировать ее. Звучит сложно? На самом деле нет. Просто представьте, что компилятор — это переводчик, который превращает ваш красивый код в язык, понятный процессору.

Кстати, о компиляторах. Есть несколько популярных вариантов: GCC, Clang, MSVC и другие. Мы будем использовать Clang 16-й версии. Почему? Потому что он удобный, быстрый и просто крутой. При проверке задач мы будем использовать такие ключи компиляции:

clang++ --std=c++20 -O3 -fsanitize=address,undefined -Wall -Wextra -Werror

Не пугайтесь этих строчек! Это просто настройки, которые помогают находить ошибки и делать ваш код лучше.

Теперь немного о стандартах. C++ развивается, и каждые несколько лет появляется новый стандарт языка. Мы будем ориентироваться на C++20. Это как последняя версия вашего любимого приложения — только для программистов.

Если вы думаете, что написание программ на C++ требует каких-то особенных инструментов, то вы ошибаетесь. Можно писать код даже в блокноте. Но, конечно, удобнее использовать среду разработки (IDE). Например, Visual Studio, Eclipse или Qt Creator. Мы же будем запускать компилятор прямо из консоли. Так вы почувствуете себя настоящими хакерами из фильмов.

А теперь давайте напишем нашу первую программу. Знаете, что это будет? Конечно же, "Hello, world!" — традиция, которую обязан соблюдать каждый программист. Вот она:

#include <iostream>

int main() {

std::cout << "Hello, world!\n";

}

Выглядит просто, правда? Но давайте разберем, что здесь происходит. #include <iostream> — это подключение библиотеки для работы с потоками ввода-вывода. std::cout — это поток вывода, который отправляет текст на экран. А \n — это символ перевода строки.

Чтобы скомпилировать эту программу, откройте терминал и введите:

clang++ hello.cpp -o hello

После этого запустите исполняемый файл:

./hello

И вот оно — магическое сообщение: "Hello, world!"

Но что, если вы хотите сделать программу чуть интереснее? Например, спросить имя пользователя и поприветствовать его персонально? Тогда вам понадобится поток ввода std::cin. Вот пример:

#include <iostream>

#include <string>

int main() {

std::string name;

std::cout << "What is your name?\n";

std::cin >> name;

std::cout << "Hello, " << name << "!\n";

}

Обратите внимание: если пользователь введет несколько слов через пробел, программа "увидит" только первое. Чтобы считать всю строку целиком, используйте функцию std::getline.

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

Переменные и типы данных

В программировании переменные — это контейнеры для хранения данных. В C++ каждая переменная имеет определенный тип, который указывает, сколько памяти она занимает и какие операции с ней можно выполнять. Вот несколько базовых типов:

  • int — целые числа (например, 42).

  • float и double — числа с плавающей точкой (дробные числа). float обычно занимает 4 байта, а double — 8.

  • char — символы (например, 'A').

  • bool — логический тип, принимающий значения true или false.

Пример объявления переменных:

int age = 25;

double pi = 3.14159;

char grade = 'A';

bool isProgrammer = true;

Обратите внимание: в C++ важно инициализировать переменные перед их использованием. Если этого не сделать, то при попытке чтения значения такой переменной может возникнуть неопределенное поведение (UB — undefined behavior).

Области видимости

В C++ существует понятие области видимости (scope) переменной. Это означает, что переменная доступна только внутри блока кода, в котором она была объявлена. Например:

#include <iostream>

int globalVariable = 1; // Глобальная переменная

int main() {

int localVariable = 2; // Локальная переменная

{

int innerVariable = 3; // Локальная переменная внутри блока

std::cout << globalVariable << " " << localVariable << " " << innerVariable << "\n";

}

// Здесь innerVariable недоступна

std::cout << globalVariable << " " << localVariable << "\n";

}

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

Арифметические операции

C++ поддерживает все стандартные арифметические операции: сложение (+), вычитание (-), умножение (*), деление (/) и взятие остатка от деления (%). Пример:

int a = 7, b = 3;

int sum = a + b; // 10

int difference = a - b; // 4

int product = a * b; // 21

int quotient = a / b; // 2 (целочисленное деление)

int remainder = a % b; // 1 (остаток от деления)

Если вам нужно работать с дробными числами, используйте тип double и явное приведение типов:

double exactQuotient = static_cast<double>(a) / b; // 2.333...

Условия и циклы

Одним из ключевых элементов программирования являются условия и циклы. Они позволяют управлять потоком выполнения программы. Вот пример использования условного оператора if:

int number = 10;

if (number > 0) {

std::cout << "Число положительное.\n";

} else if (number < 0) {

std::cout << "Число отрицательное.\n";

} else {

std::cout << "Число равно нулю.\n";

}

Циклы позволяют повторять выполнение блока кода несколько раз. Вот пример цикла for, который выводит числа от 1 до 5:

for (int i = 1; i <= 5; ++i) {

std::cout << i << "\n";

}

А вот пример цикла while, который выполняется, пока условие истинно:

int counter = 0;

while (counter < 5) {

std::cout << "Счетчик: " << counter << "\n";

++counter;

}

Задача 1: "Калькулятор"

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

Пример работы программы:

Введите первое число: 10

Введите второе число: 5

Выберите операцию (+, -, *, /): *

Результат: 50

Подсказка: Используйте std::cin для ввода данных и условный оператор if для выбора операции. Не забудьте обработать деление на ноль!


Задача 2: "Угадай число"

Описание: Напишите программу, которая загадывает случайное число от 1 до 100 и предлагает пользователю угадать его. После каждой попытки программа должна сообщать, было ли число больше или меньше загаданного.

Пример работы программы:

Я загадал число от 1 до 100. Попробуйте угадать!

Ваша догадка: 50

Мое число меньше.

Ваша догадка: 25

Мое число больше.

Ваша догадка: 30

Поздравляю! Вы угадали за 3 попытки!

Подсказка: Для генерации случайного числа используйте функцию rand() из заголовочного файла <cstdlib>. Чтобы сделать число действительно случайным, добавьте вызов srand(time(0)) из <ctime> в начале программы.


Задача 3: "Факториал"

Описание: Напишите программу, которая вычисляет факториал числа, введенного пользователем. Факториал числа n (обозначается как n!) — это произведение всех целых чисел от 1 до n. Например, 5!=5×4×3×2×1=120.

Пример работы программы:

Введите число: 5

Факториал числа 5 равен 120.

Подсказка: Используйте цикл for для вычисления произведения. Обратите внимание, что факториал определен только для неотрицательных целых чисел.

Задача 4: "Таблица умножения"

Описание: Напишите программу, которая выводит таблицу умножения для числа, введенного пользователем. Таблица должна содержать все произведения от 1 до 10.

Пример работы программы:

Введите число: 7

Таблица умножения для числа 7:

7 x 1 = 7

7 x 2 = 14

7 x 3 = 21

...

7 x 10 = 70

Подсказка: Используйте цикл for для перебора множителей от 1 до 10.

Задача 5: "Сумма цифр числа"

Описание: Напишите программу, которая принимает целое число и вычисляет сумму его цифр.

Пример работы программы:

Введите число: 1234

Сумма цифр числа 1234 равна 10.

Подсказка: Преобразуйте число в строку с помощью std::to_string, чтобы легко получить доступ к каждой цифре. Альтернативно, используйте операции деления и взятия остатка для работы с числами напрямую.


Задача 6: "Палиндром"

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

Пример работы программы:

Введите строку: радар

Строка "радар" является палиндромом.

Введите строку: hello

Строка "hello" не является палиндромом.

Подсказка: Используйте функцию std::reverse из заголовочного файла <algorithm> для создания перевернутой версии строки. Сравните исходную строку с перевернутой.


Задача 7: "Игра в кости"

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

Пример работы программы:

Бросаем кости...

Первая кость: 4

Вторая кость: 6

Общее количество очков: 10

Подсказка: Используйте функцию rand() для генерации случайных чисел от 1 до 6.

Показать полностью
[моё] Гайд Программирование C++ IT Длиннопост
16
7
Sigurd2012
Sigurd2012
5 месяцев назад
Timeend

Мой вариант "Змейки" на С++ (пока предварительный)⁠⁠

А вот мой мини-мультсериал "в стиле старых игр" (тоже С++):

  • Retro Game Stories - 5 серий

Показать полностью
[моё] Игры Ретро-игры Программирование C++ Игра змейка Видео Без звука
3
8
0sadchi
0sadchi
5 месяцев назад
Лига Разработчиков Видеоигр

Свой Cheat Engine с нуля! Часть 1 - Получаем список процессов и модули в нем⁠⁠

Чтобы сформировать понимание, как происходит получение списка процессов, просто заглянем в исходники самого Cheat Engine.

Здесь у нас есть процедура GetProcessList, в которую мы подаем массив строк, в который она запишем нам имена и айди процессов.

Первое, на что обратим внимание - структура, куда записывается информация о процесе, в СЕ она выглядит так

Свой Cheat Engine с нуля! Часть 1 - Получаем список процессов и модули в нем Windows, Программирование, Cheat Engine, C++, Hacking, Длиннопост

Мы можем ее записать так.

Свой Cheat Engine с нуля! Часть 1 - Получаем список процессов и модули в нем Windows, Программирование, Cheat Engine, C++, Hacking, Длиннопост

Далее в процедуре идет блок с переменными

Свой Cheat Engine с нуля! Часть 1 - Получаем список процессов и модули в нем Windows, Программирование, Cheat Engine, C++, Hacking, Длиннопост

Как итог я оставил так

Свой Cheat Engine с нуля! Часть 1 - Получаем список процессов и модули в нем Windows, Программирование, Cheat Engine, C++, Hacking, Длиннопост

Для замены под C++ объекта ProcessList: TStrings, я использовал std::unordered_map<std::wstring, PProcessListInfo>& process_list. Потому что в коде, была логика схожая с мапой, когда у нас по имени процесса идет связка с объектом, содержащим информацию о нем (фактически один ProcessID..)

Свой Cheat Engine с нуля! Часть 1 - Получаем список процессов и модули в нем Windows, Программирование, Cheat Engine, C++, Hacking, Длиннопост

Что у нас эквивалентно

Свой Cheat Engine с нуля! Часть 1 - Получаем список процессов и модули в нем Windows, Программирование, Cheat Engine, C++, Hacking, Длиннопост

И в конце при необходимости это включается в лист

Свой Cheat Engine с нуля! Часть 1 - Получаем список процессов и модули в нем Windows, Программирование, Cheat Engine, C++, Hacking, Длиннопост

Заменил на

Свой Cheat Engine с нуля! Часть 1 - Получаем список процессов и модули в нем Windows, Программирование, Cheat Engine, C++, Hacking, Длиннопост

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

Но тут мое любопытство увело меня в сторону от Cheat Engine, и я решил посмотреть, что там у Process Hacker, это утилита позволяет работать с процессами. Самой интересной частью является - список модулей. Потому, что там сразу можно увидеть кто-где и какой размер в памяти занимает каждый из них.

Через поиск по файла по фразе EnumModules я вышел на вот такую вот функцию

Свой Cheat Engine с нуля! Часть 1 - Получаем список процессов и модули в нем Windows, Программирование, Cheat Engine, C++, Hacking, Длиннопост

так же у нее есть 32битная реализация

Свой Cheat Engine с нуля! Часть 1 - Получаем список процессов и модули в нем Windows, Программирование, Cheat Engine, C++, Hacking, Длиннопост

Результатом работы оных будет вот такая вот структура

Свой Cheat Engine с нуля! Часть 1 - Получаем список процессов и модули в нем Windows, Программирование, Cheat Engine, C++, Hacking, Длиннопост
Свой Cheat Engine с нуля! Часть 1 - Получаем список процессов и модули в нем Windows, Программирование, Cheat Engine, C++, Hacking, Длиннопост

Самыми интересными для нас будут PVOID DllBase - начало модуля относительно процесса , ULONG SizeOfImage - размер модуля (сколько байт он занимает внутри процесса) и UNICODE_STRING FullDllName. Но с именем все не так просто. Структура выглядит так

Свой Cheat Engine с нуля! Часть 1 - Получаем список процессов и модули в нем Windows, Программирование, Cheat Engine, C++, Hacking, Длиннопост

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

Свой Cheat Engine с нуля! Часть 1 - Получаем список процессов и модули в нем Windows, Программирование, Cheat Engine, C++, Hacking, Длиннопост

И тут я на радостях побежал смотреть все модули, но не тут-то было.. Если получить список процессов вполне себе легитимная процедура, то читать память другого процесса уже не всегда дозволяется авторами софта. Но на этот случай у ProcessHacker есть свой собственный драйвер, на то он и хакер.

Все, до чего я докопался - это метод

Свой Cheat Engine с нуля! Часть 1 - Получаем список процессов и модули в нем Windows, Программирование, Cheat Engine, C++, Hacking, Длиннопост

Данные о драйвере выглядят так

Свой Cheat Engine с нуля! Часть 1 - Получаем список процессов и модули в нем Windows, Программирование, Cheat Engine, C++, Hacking, Длиннопост

Но, к сожалению, с наскока подключиться к драйверу не удалось и лучший ответ, который я получилъ

Свой Cheat Engine с нуля! Часть 1 - Получаем список процессов и модули в нем Windows, Программирование, Cheat Engine, C++, Hacking, Длиннопост

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

Конец! А кто слушал - можете прокачать свои навыки на крутейшем курсе по реверсу ММОРПГ :)

Показать полностью 15
[моё] Windows Программирование Cheat Engine C++ Hacking Длиннопост
2
3
georgiyozhegov
georgiyozhegov
5 месяцев назад
Лига программистов
Серия Программирование

Читщит По Умным Указателям⁠⁠

Читщит По Умным Указателям Обучение, Rust, Программирование, C++, Длиннопост

Наглядная иллюстрация того, что может случиться с C++ программистами.

В Rust необычная схема управления памятью. Он не использует сборщик мусора, как в Java и Go, что делает его быстрым. Скорость Rust сопоставима со скоростью C.

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

В статье специально использованы простейшие примеры, чтобы понять их было легче.

Типы

Box

Нужен для хранения объектов в куче, а не на стеке.

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

Пример кода, который не будет работать.

struct Expression {

operator: Operator,

left: Expression, // Ошибка: recursive type has infinite size

right: Expression, // Ошибка: recursive type has infinite size

}

Чинится обертыванием left и right в Box.

struct Expression {

operator: Operator,

left: Box<Expression>,

right: Box<Expression>,

}

Rc

Позволяет нескольким переменным владеть одним объектом размещенным в куче.

Не работающий код.

let a = "Hello, World!".to_string();

let b = a;

let c = a; // Ошибка: use of moved value

Чтобы он заработал, добавим Rc.

let a = Rc::new("Hello, World!".to_string());

let b = Rc::clone(&a);

let c = Rc::clone(&a);

Код также будет работать если мы скопируем объект.

let a = "Hello, World!".to_string();

let b = a.clone();

let c = a;

Но прямое копирование может серьезно повредить производительности. Преимущество Rc в том, что при присваивании не создаётся новый объект, а даётся ссылка на уже существующий.

Arc

То же что и Rc, но безопасное для использования в многопоточных приложениях. Это значит, что его можно использовать из разных потоков, не боясь гонок данных.

let a = Arc::new(1);

let b = Arc::clone(&a);

let c = Arc::clone(&a);

Дороже с точки зрения производительности из-за способа подсчёта ссылок.

RefCell

Позволяет изменять данные внутри себя даже если объявлен как неизменяемый.

let a = RefCell::new(1);

*a.borrow_mut() += 1;

dbg!(a); // 2

Комбо

RefCell часто комбинируют с Rc в виде Rc<RefCell<T>>. Это позволяет каждому владельцу ссылки изменять общий объект.

let a = Rc::new(RefCell::new(1));

let b = Rc::clone(&a);

let c = Rc::clone(&a);

*b.borrow_mut() += 1;

dbg!(&a); // 2

dbg!(&c); // Тоже 2

*c.borrow_mut() += 1;

dbg!(&a); // 3

dbg!(&b); // Тоже 3

Заключение

Главное преимущество умных указателей – избегание ошибок типа segfault и выстрелов в ногу, характерных для C и C++, сохраняя при этом удобство использования.

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

Показать полностью
[моё] Обучение Rust Программирование C++ Длиннопост
16
Fantomas1994
Fantomas1994
6 месяцев назад

Рубрика "Сломай нейронку". Опасные итераторы)⁠⁠

Рубрика "Сломай нейронку". Опасные итераторы) C++, Программирование, Ооп, ChatGPT, Длиннопост, Скриншот
Показать полностью 1
[моё] C++ Программирование Ооп ChatGPT Длиннопост Скриншот
16
11
neverending.cpp
neverending.cpp
6 месяцев назад
Лига программистов C/C++

Книга по C++, которую ты обязан прочитать в 2025 году⁠⁠

Я почему-то уверен, что она у тебя уже есть. Либо в списке литературы для самообразования, либо где-то среди скачанных pdf, а может, даже в печатном виде. Возможно, ты даже начинал её читать, но… работа, таски, собеседования… деньги вроде и так платят… и ты так и не осилил Мейерса "Эффективный и современный С++".

А ведь именно эта книга — ключ, который поможет тебе пробить потолок уровня middle и начать движение к senior.

Да, можно скачать список из 400 популярных вопросов, выучить их и бодро ответить на вопрос: «Расскажи про std::unique_ptr». А потом тебе прилетает дополнительный вопрос: «А как изменится размер std::unique_ptr при использовании пользовательского удалителя?» Иии… Я не буду додумывать твой уровень знаний. Попробуй сам ответить на этот вопрос и поставь себе оценку🙂
И это только один из примеров тонких нюансов, которые описаны в этой книге и которые реально спрашивают на собеседованиях.

Ещё одна сильная сторона книги: почти каждая фича современного C++ иллюстрируется примерами её использования в реальном проде. А это большая редкость для технической литературы.

Хватит откладывать эту книгу на «потом». Поставь цель на этот год и, наконец-то, найди время, чтобы прочитать 300 страниц "Эффективного и современного С++".

Книга по C++, которую ты обязан прочитать в 2025 году Кросспостинг, Pikabu Publish Bot, IT, C++, Программирование, Книги, Самообразование
Показать полностью 1
[моё] Кросспостинг Pikabu Publish Bot IT C++ Программирование Книги Самообразование
27
Партнёрский материал Реклама
specials
specials

Сколько кнопок было на вашем тамагочи: три или четыре?⁠⁠

Четыре — это на богатом, три — это на каноничном. В нашем тамагочи, конечно, три. Заходите в игру и вырастите очаровательную квокку.

Игры Тамагочи Награда Ностальгия
11
0sadchi
0sadchi
6 месяцев назад
Лига Разработчиков Видеоигр

Похищаем CheatEngine на C++ с нуля. Часть 0 - Введение⁠⁠

🌐 Введение

Данной статьей я хочу продемонстрировать процесс погружения в неизвестную сферу, методы и средства для сбора информации. Чтобы раз и навсегда закрыть вопрос какие материалы “почитать”, ведь, действуя по гайду “я повторил, но ничего не понял”.

Что именно будем делать? Попробуем без особых знаний залезть в исходники софта для отладки и модификации кода, под названием Cheat Engine. Он создавался годами, а наша задача — апроприировать эти знания за короткий промежуток времени!

👤 Что такое Cheat Engine?

Cheat Engine — это мощный инструмент для реверс-инжиниринга и модификации кода. Хотя он позиционируется как “Чит Движок”, он фактически способен конкурировать с любыми дебаггерами по ряду причин:

  • 🔒 Оснащён собственным драйвером, который даёт более высокий уровень прав и скрытность.

  • 🕹️ Обладает встроенным гипервизором, который можно загрузить прямо в рантайме ОС.

  • 🌟 Бесплатный и открытый исходный код делает его удобным для изучения.

💪 Зачем писать свой Cheat Engine?

Мы поняли, что это классная штука, она бесплатная, открытая и она работает. Так зачем же его писать самим?!
Главное - 🎓 Это сложная и интересная задача. Ну и я ни на что не намекаю, но …😉

Похищаем CheatEngine на C++ с нуля. Часть 0 - Введение C++, Читер, Движок, Windows, Игры, Длиннопост

Не сложно догадаться, что завести такой пет-проект в портфолио будет не плохо.

🔄 План работы

Чтобы создать минимально рабочий прототип, нам нужно реализовать ключевые функции:

  1. 🔐 Подключение к процессу.

  2. 🤖 Чтение и сканирование памяти.

  3. 🛠️ Редактирование памяти.

  4. 🔄 Таблица с найденными адресами.

  5. 📝 Дизассемблирование кода.

  6. 🏢 Отображение списка загруженных библиотек.

  7. 🌧️ Отладка (брейки, стек вызовов, регистры).

🔍 Исследуем исходники Cheat Engine

Открываем репозиторий Cheat Engine и видим несколько важных директорий:

Похищаем CheatEngine на C++ с нуля. Часть 0 - Введение C++, Читер, Движок, Windows, Игры, Длиннопост
  • Cheat Engine — основной код.

  • DBKKernel — проект драйвера.

  • DBVM — гипервизор.

  • lua — движок для скриптов.

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

😅 Тут нас ждёт сюрприз: Cheat Engine написан на Паскале!

  • .lfm — GUI формы.

  • .pas — исходники с функциями.️️ 🔖 (они-то нам и нужны)

🌟 Разбираемся с кодом

Заглянув в основной проект, можно заметить, что там ку-у-у-у-ча файлов, но пугаться не стоит, так как главных всего-то ничего! А именно…

🔄 ProcessList.pas
    Этот файл нужен для сбора и хранения информации о процессах.

procedure GetProcessList(ProcessList: TStrings; NoPID: boolean=false; noProcessInfo: boolean=false);

Перегрузка процедуры для управления выводом информации о процессах.

Похищаем CheatEngine на C++ с нуля. Часть 0 - Введение C++, Читер, Движок, Windows, Игры, Длиннопост
Похищаем CheatEngine на C++ с нуля. Часть 0 - Введение C++, Читер, Движок, Windows, Игры, Длиннопост
Похищаем CheatEngine на C++ с нуля. Часть 0 - Введение C++, Читер, Движок, Windows, Игры, Длиннопост

Чтобы продвинуться дальше, просто забиваем в поиск по файлам название функции GetProcessList, это приведет нас к следующему файлу и еще одной интересной функции…

Похищаем CheatEngine на C++ с нуля. Часть 0 - Введение C++, Читер, Движок, Windows, Игры, Длиннопост

🔄 MainUnit.pas (Это главный файл с логикой для GUI форм)
    Здесь вызывается Open_Process, который используется во всех интерфейсах дебаггера (Kernel, DBVM).

🔄 CEFuncProc.pas
    Тут находится реализация Open_Process.

🔄 NewKernelHandler.pas
     Содержит ключевые функции, такие как:

  function ReadProcessMemory(...);   function WriteProcessMemory(...);

🔄 Disassembler.pas
    Файл на 16 000 строк, отвечающий за дизассемблирование кода.

🚀 Итоги

Теперь мы знаем как:
  ✅ Получать список процессов.
  ✅ Открывать хендл к процессу.
  ✅ Читать и записывать память.

Следующий шаг — разобраться с отладчиком и дизассемблером! 💪

Функции отладчика находятся все в том же NewKernelHandler.pas, они так же представлены перегрузками для разных интейфейсов: winapi, driver, server и т.д. Но в данном случае мы пока обратим внимание на winapi и уже после будет шаг за шагом разбирать другие методы работы.

Ключевыми будут 👇

// Получение адреса функции GetThreadContext из библиотеки WindowsKernel и присваивание его переменной GetThreadContext GetThreadContext:=GetProcAddress(WindowsKernel,'GetThreadContext');

// Получение адреса функции SetThreadContext из библиотеки WindowsKernel и присваивание его переменной SetThreadContext SetThreadContext:=GetProcAddress(WindowsKernel,'SetThreadContext');

🤏 Именно через SetThreadContext мы и будем устанавливать аппаратные точки останова, изменяя регистр DRx (Debug Registers).

🔹 Как установить хардверный бряк через SetThreadContext?

  • 1️⃣ Использовать GetThreadContext, чтобы получить текущий контекст потока.

  • 2️⃣ Изменить один из DR0–DR3 (адрес бряка).

  • 3️⃣ Настроить DR7 для активации бряка.

  • 4️⃣ Применить изменения через SetThreadContext.

🔹 Пример кода

CONTEXT ctx; ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS; GetThreadContext(hThread, &ctx);

ctx.Dr0 = targetAddress; // Адрес для бряка

ctx.Dr7 |= 1; // Включаем бряк

SetThreadContext(hThread, &ctx);

📌 Важно: бряк привязан к конкретному потоку, а не всему процессу.

👁️👁️👁️ Там же видим

// 🔍 Получение адреса функции Wow64GetThreadContext из библиотеки WindowsKernel и присваивание его переменной Wow64GetThreadContext

Wow64GetThreadContext:=GetProcAddress(WindowsKernel,'Wow64GetThreadContext');

// 🔍 Получение адреса функции Wow64SetThreadContext из библиотеки WindowsKernel и присваивание его переменной Wow64SetThreadContext

Wow64SetThreadContext:=GetProcAddress(WindowsKernel,'Wow64SetThreadContext');

SuspendThread:=GetProcAddress(WindowsKernel,'SuspendThread'); // ⏸️ Получение адреса функции SuspendThread из библиотеки WindowsKernel, которая используется для приостановки выполнения потока

ResumeThread:=GetProcAddress(WindowsKernel,'ResumeThread'); // ▶️ Получение адреса функции ResumeThread из библиотеки WindowsKernel, которая используется для возобновления выполнения ранее приостановленного потока

WaitForDebugEvent:=GetProcAddress(WindowsKernel,'WaitForDebugEvent'); // ⏳ Получение адреса функции WaitForDebugEvent из библиотеки WindowsKernel, которая используется для ожидания события отладки в процессе или потоке

ContinueDebugEvent:=GetProcAddress(WindowsKernel,'ContinueDebugEvent'); // 🔄 Получение адреса функции ContinueDebugEvent из библиотеки WindowsKernel, которая используется для продолжения выполнения после обработки события отладки

DebugActiveProcess:=GetProcAddress(WindowsKernel,'DebugActiveProcess'); // 🛠️ Получение адреса функции DebugActiveProcess из библиотеки WindowsKernel, которая используется для начала отладки процесса по его идентификатору

Здесь же видим непонятный WindowsKernel, пробуем поискать в файле и находим:

WindowsKernel: Thandle; // 🏗️ Переменная, хранящая дескриптор ядра операционной системы Windows

Но это только объявление, пробуем прощелкать далее и находим определение:

WindowsKernel:=LoadLibrary('Kernel32.dll'); // 📦 Попытка загрузить библиотеку ядра Windows (Kernel32.dll) и сохранение дескриптора в переменную WindowsKernel. // ❌ Если библиотека не найдена, то WindowsKernel будет равен 0.

Этого достаточно для базовой работы с процессами. Остается поглядеть, что там в Disassembler’е.
Как мы помним, там 16 000 строк кода, и все, что они делают, так это проверяют каждый байт на константное значение.
Если совпадает, то устанавливают строковую мнемонику (ADD, MOV и др.).

Рассмотрим поближе. У нас есть базовый объект дизассемблера, defaultDisassebler:

defaultDisassembler:=TDisassembler.create; // 🛠️ Создаем объект по умолчанию и присваиваем его глобальной переменной.

Который инициализируется методом create в классе TDisassembler,
далее на участок памяти вызывается функция disassemble, которая возвращает строку.
Начинается функция на 1624 строке, а заканчивается на 15710 строке.

Как уже выше упомянуто, почти все эти строки занимает switch,
который проверяет байты и отдает назад название инструкции.

case memory[0] of //opcode

$00 : begin

//🏹🏹

if (aggressivealignment and (((offset) and $f)=0) and (memory[1]<>0) ) or ((memory[1]=$55) and (memory[2]=$89) and (memory[3]=$e5)) then

begin

description:='Filler'; lastdisassembledata.opcode:='db'; LastDisassembleData.parameters:=inttohex(memory[0],2);

end

else

begin

description:='Add';

//🏹🏹

lastdisassembledata.opcode:='add';

lastdisassembledata.parameters:=modrm(memory,prefix2,1,2,last)+r8(memory[1]); inc(offset,last-1);

end;

end;

$01 : begin....

Думаю, на этом можно закончить введение, более подробно рассмотрим каждый из методов уже на практике, когда начнем писать свой mega-omega чит-движок с плюшками.

На этом откланяюсь, а все претензии и пожелания можно писать сюда 👉 https://t.me/osiechan/52, здесь же можно скачать исходные файлы с комментариями на каждой строке (да-да, даже на 16 000 строк) и pdf статьи.

А прокачать свой навыки чито-строителя можно на бесплатном, открытом курсе по созданию бота для мморпг 👉 https://t.me/osiechan/41.

Спасибо за внимание :з.

Показать полностью 6
[моё] C++ Читер Движок Windows Игры Длиннопост
1
Посты не найдены
О нас
О Пикабу Контакты Реклама Сообщить об ошибке Сообщить о нарушении законодательства Отзывы и предложения Новости Пикабу Мобильное приложение RSS
Информация
Помощь Кодекс Пикабу Команда Пикабу Конфиденциальность Правила соцсети О рекомендациях О компании
Наши проекты
Блоги Работа Промокоды Игры Курсы
Партнёры
Промокоды Биг Гик Промокоды Lamoda Промокоды Мвидео Промокоды Яндекс Директ Промокоды Отелло Промокоды Aroma Butik Промокоды Яндекс Путешествия Постила Футбол сегодня
На информационном ресурсе Pikabu.ru применяются рекомендательные технологии