С/С++ Portal | Программирование – Telegram
С/С++ Portal | Программирование
16.7K subscribers
1.05K photos
209 videos
23 files
793 links
Присоединяйтесь к нашему каналу и погрузитесь в мир для C/C++-разработчика

Связь: @devmangx

РКН: https://clck.ru/3Foc4d
Download Telegram
Интересный факт: у C есть веб-сайт.

c-language.org

👉 @Cpportal
Please open Telegram to view this post
VIEW IN TELEGRAM
22🤯10🔥8👍4😁2
Обычно думают что перегрузка функций это чисто фича C++, но в C11 есть _Generic, который позволяет делать диспетчинг по типу на этапе компиляции. Это стандартный C, без расширений и без рантайм-оверхеда.

👉 @Cpportal
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥267💊2
В C можно намеренно докладывать данные сразу после структуры. Один malloc, один сплошной блок в памяти. Полезно если понимаешь что делаешь, опасно если нет.

👉 @Cpportal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍215👎1🔥1👀1
Каждый раз когда вижу цикл ради вывода пробелов, вспоминаю что printf решил эту задачу ещё десятки лет назад.

Ширину можно передавать динамически. %*s в C делает больше работы чем многие думают.

👉 @Cpportal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍203😁3
Создание процесса в Linux устроено хитрее, чем кажется.

Можно подумать, что fork() тупо дублирует весь процесс: хип, стек и так далее. Наивно это выглядело бы как полный копипаст всей памяти.

Но копировать гигабайты RAM только чтобы запустить shell-команду? Система бы просто подвисала.

На деле используется Copy-on-Write (COW).

Таблицы страниц родителя и потомка указывают на одни и те же физические фреймы памяти.

В момент когда один из процессов пытается записать что-то в память, ядро ловит page fault, копирует только конкретную страницу на 4 КБ и продолжает выполнение.

fork() интересен ещё тем, что возвращается дважды.

Один раз в родителя (возвращает PID ребёнка), и один раз в ребёнка (возвращает 0).

Так вселенная раскалывается надвое, и один участок кода обслуживает два пути выполнения.

#include <unistd.h>
#include <stdio.h>

int main() {
pid_t pid = fork();

if (pid == 0) {
printf("I am the child!\n");
} else {
printf("I am the parent of %d\n", pid);
}

return 0;
}


Под капотом, однако, glibc при вызове fork() даже не вызывает системный вызов fork!

Она вызывает clone — швейцарский нож, который лежит в основе создания тредов и других задач.

Системный вызов fork в ядре остался, но glibc трактует его как clone с настройками для классического дублирования процесса.


👉 @Cpportal
Please open Telegram to view this post
VIEW IN TELEGRAM
12👍9
Context Pattern

FP, OOP, процедурщина и декларативщина объединены для создания единственного и последнего дизайн-паттерна, который вам когда-либо понадобится.

Одна структура (record), содержащая все зависимости, и которую вы явно передаете в каждую функцию.

Больше никакого наследования.
Больше никаких классов и методов.
Больше никакого dependency injection.
Больше никакого singleton.
Больше никаких private/public.
Моки проще некуда.

Это единственный паттерн, который нужен для структурирования ЛЮБОГО ПРИЛОЖЕНИЯ, В ЛЮБОЙ ИНДУСТРИИ (микросервис, компилятор, космическая система).

В Haskell это известно как «шаблон ручки» (The Handle Pattern)

👉 @Cpportal
Please open Telegram to view this post
VIEW IN TELEGRAM
11👎5🔥5🥱3👍1
Много C-программ до сих пор вручную пишут парсинг циклом под простые форматы. Хотя в стандартной библиотеке уже есть scanset'ы в scanf для парсинга по разделителям.

Если задать ширину полей и проверять код возврата, это полностью корректный ISO C. Без сторонних библиотек и без зависимости от компилятора.

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

👉 @Cpportal
Please open Telegram to view this post
VIEW IN TELEGRAM
17👍8😁1
Разработчик завершил реализацию собственного ECS-движка на C и заявил, что его система примерно в 17 раз быстрее Unity DOTS в веб-среде. В демонстрационном тесте симуляция 100 тысяч boids работала на ~90 FPS против ~17 FPS у Unity.

Автор пообещал позже выложить исходники и ссылку на демо. Тестовые параметры:

• Windows 10 64-bit
• Chrome с включённым force-high-performance-gpu
• CPU: AMD Ryzen 7 5800H (8C/16T)
• GPU: NVIDIA GeForce RTX 3060 Laptop
• RAM: 32 GB

В сцене рендерилось ~31 млн треугольников на кадр с PBR-освещением. Имплементация ECS была выполнена максимально близко к репозиторию Unity EntitiesSamples. В Unity были активированы и WebGPU, и wasm-threads, обе сборки — release с агрессивной оптимизацией.

Отмечается, что разница в FPS в демке составляет около 5x, поскольку упор идет в GPU. При этом сама ECS-симуляция на кастомном движке работает на ~430 FPS против ~22 FPS у Unity. Время измерялось одинаково в обоих случаях — по обновлению ECS World.

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

👉 @Cpportal
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
27👍7🔥3
This media is not supported in your browser
VIEW IN TELEGRAM
Введение в кучу и динамическую память

Источник: смотреть

👉 @Cpportal
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔53👍1
Не сливаем байты на булевы флаги.

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

Вместо 4 отдельных int ты можешь впихнуть 32 флага всего в 4 байта.

Только не забывай: выравнивание и раскладка зависят от реализации, так что проверяй на целевой платформе.

#include <stdio.h>

struct user_flags {
unsigned int is_active : 1; // по одному биту на поле
unsigned int is_admin : 1;
unsigned int is_banned : 1;
unsigned int email_verified : 1;
unsigned int has_two_factor : 1;
unsigned int is_premium : 1;
unsigned int can_post : 1;
unsigned int can_comment : 1;
unsigned int reserved : 24; // пока не используется
};

int main() {
struct user_flags current_user = {0};

current_user.is_active = 1;
current_user.is_admin = 1;
current_user.email_verified = 1;
current_user.is_premium = 1;

printf("этой структуре нужно всего %zu байт (влезает в 4!)\n", sizeof(current_user));

if (current_user.is_admin && current_user.is_premium) {
printf("у пользователя есть admin и premium доступ\n");
}

// перевернуть статус banned
current_user.is_banned = !current_user.is_banned;

return 0;
}


👉 @Cpportal
Please open Telegram to view this post
VIEW IN TELEGRAM
18👍4🔥3
Это единственный верный путь держать enum и строки в C в идеальном sync.
Один источник правды, без ручных маппингов и без расхождений.

X-Macros генерирует как перечисления, так и строки из одного и того же списка.
Чистый стандартный C. Используется там, где действительно важна корректность.

#include <stdio.h>

#define COLOR_TABLE \
X(RED, "Красный цвет") \
X(GREEN, "Зеленый цвет") \
X(BLUE, "Синий цвет") \
X(UNKNOWN, "Неизвестная сущность")

typedef enum {
#define X(name, str) COLOR_##name,
COLOR_TABLE
#undef X
} Color;

const char* ColorStrings[] = {
#define X(name, str) str,
COLOR_TABLE
#undef X
};

int main(void) {
Color c = COLOR_GREEN;
printf("Enum ID: %d соответствует строке: %s\n", c, ColorStrings[c]);
return 0;
}


👉 @Cpportal
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥18👍75🤔1🌚1
const в C это не про оптимизацию.

Он задает, что функция имеет право делать.

Нарушишь контракт и компилятор тебя остановит.

Это сильнее, чем комментарий.

#include <stddef.h>

size_t checksum(const unsigned char *data, size_t len)
{
size_t sum = 0;
for (size_t i = 0; i < len; ++i)
sum += data[i];
return sum;
}


👉 @Cpportal
Please open Telegram to view this post
VIEW IN TELEGRAM
23
Zen C теперь публично доступен!

С этим новым языком можно писать в стиле высокоуровневых языков, но при этом иметь доступ ко всей экосистеме C и не терять в производительности.

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

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

👉 @Cpportal
Please open Telegram to view this post
VIEW IN TELEGRAM
13👍7😁5🥱3🤣2
This media is not supported in your browser
VIEW IN TELEGRAM
Преобразование бинарного числа в десятичное на C.

Есть несколько способов сделать это. Вот один из примеров.

👉 @Cpportal
Please open Telegram to view this post
VIEW IN TELEGRAM
19💊3👍1👎1😁1
Если твоему C-коду нужно 5 временных структур, тебе не нужен более безопасный язык, тебе нужно научиться писать на C.

Многие называют C небезопасным и грязным, игнорируя compound literals и designated initializers.
Собирай структуры прямо в месте вызова: без временных переменных, без багов из-за порядка и без лишних накладных расходов.

sendmsg(sock,
&(struct msghdr){
.msg_name = &(struct sockaddr_in){
.sin_family = AF_INET,
.sin_port = htons(9000),
.sin_addr = { .s_addr = INADDR_ANY }
},
.msg_namelen = sizeof(struct sockaddr_in),
.msg_iov = iov,
.msg_iovlen = 1,
},
0
);


👉 @Cpportal
Please open Telegram to view this post
VIEW IN TELEGRAM
10🔥9🤔7👍5😁2
Media is too big
VIEW IN TELEGRAM
В отличие от Windows, в Linux нет встроенного message box, который можно показать обычному пользователю, чтобы ему не пришлось заново запускать программу из терминала или лезть в логи.

Так что давайте сделаем свой с нуля на C, без GUI-тулкитов! 👏

Версия с чуть выше битрейтом

GitHub со всеми исходниками

👉 @Cpportal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍63🔥3