• XSS.stack #1 – первый литературный журнал от юзеров форума

Изучение С в 2024

не знаю, требуется ли сейчас программирование на си. но я его изучаю
Си нужно знать вместе с плюсами, два почти идентичные ЯП которые часто используют в связке
 
Чат_гпт также пишет на путоне что угодно. Потому что в инете миллионы примеров такого кода. А спроси у него пример по винапи, не говорю о чем-то редком, да банально какие-то GDI+ - и он сливается (либо пишет бред).
Привет, такой вопрос, после Си что учить? Многие хвалят Раст, или лучше к плюсам переходить? После Си как мне кажется на плюсы легче и быстрее будет перейти.
 
Привет, такой вопрос, после Си что учить? Многие хвалят Раст, или лучше к плюсам переходить? После Си как мне кажется на плюсы легче и быстрее будет перейти.
С++
 
Привет, такой вопрос, после Си что учить? Многие хвалят Раст, или лучше к плюсам переходить?
Сразу в раст не ходи. Будет непонятно ради чего так страдать. Попиши на плюсах, шишек набей. Потом посмотришь, захочется ли тебе погружаться в сообщество токсиков, где каждая залупа норовит обвинить твой код в неидиоматичности 🙀
 
Ну а вообще, С - это такая штука, с помощью которой можно реализовать и инкапсуляцию, и наследование, и полиморфизм. Правда для этого потребуются небольшие танцы с бубном. Но инкапсуляция в С самая инкапсулированная из всех инкапсуляций.
C:
//point.h
struct Point;

struct Point*makePoint(double x, double y);

double distance(struct Point* p1, struct Point* p2);

//point.c
#include "point.h"
#include <stdlib.h>
#include <math.h>

struct Point {
    double x, y;
};

struct Point*makePoint(double x, double y)
{
    struct Point* p = malloc(sizeof(struct Point));
    p->x = x;
    p->y = y;
    return p;
}

double distance(struct Point* p1, struct Point* p2)
{
    double dx = p1->x - p2->x;
    double dy = p1->y - p2->y;
    return sqrt(dx * dx + dy * dy);
}
Чем не инкапсуляция, в прямом смысле этого слова. Более того, настоящая инкапсуляция есть только в С. В С++ поля класса приходится размещать в заголовчном файле, для того чтобы компилятор мог определить размер экземпляра каждого класса. Про шарп и прочих петухонов я вообще промолчу.

Наследование.

Тут тоже все просто.

Допустим нам понадобилась именованная точка. Значит придется добавить еще одно поле в структуру Point.

C:
//named_point.h

struct NamedPoint;

struct NamedPoint *makeNamedPoint(double x, double y, char *name);

void setName(struct NamedPoint *np,  char* name);

char *getName(struct NamedPoint *np);

//named_point.c


struct NamedPoint
{
    double x, y;
    char *name;
};

struct NamedPoint *makeNamedPoint(double x, double y, char *name)
{
    struct NamedPoint *p = malloc(sizeof(struct NamedPoint));
    p->x = x;
    p->y = y;
    p->name = name;
    return p;
}

void setName(struct NamedPoint *np,  char* name)
{
    np->name = name;
}

char *getName(struct NamedPoint *np)
{
    return np->name;
}

main.c

#include "point.h"
#include "named_point.h"
#include <stdio.h>
int main(int argc, char*argv[])
{
    struct NamedPoint *origin = makeNamedPoint(0.0,0.0,"origin");
    struct NamedPoint *topRigth = makeNamedPoint(1.0,1.0,"topRigth");
    printf("distance = %f", distance((struct Point*)origin, (struct Point*)topRigth));
}
Как бы мы без особых проблем реализовали Наследование. Но данный трюк возможен только в том случае, когда поля и порядок их объявления совпадают у "родительской" и дочерней структур.

С полиморфизмом всё несколько сложнее. Там уже используются указатели на функции. В качестве примера можно привести реализациию ввода/вывода в UNIX, где система драйверов, по сути, реализована в виде плагинов с заданным интерфейсом. Как-то так это будет выглядеть.
C:
//file.h
struct FILE
{
    void(*open)(char *name, int mode);
    void(*close)();
    int(*read)();
    void(*write)(char);
    void(*seek)(int index, int mode);
};


//file.c
#include "file.h"
    void open(char *name, int mode) {/*implementation*/}
    void close(){/*implementation*/}
    int read() {/*implementation*/}
    void write(char) {/*implementation*/}
    void seek(int index, int mode) {/*implementation*/}

struct FILE console = {open, close, read, write, seek};
Немного магии и у нас готова реализациия консолного ввода/вывода.

Если мы хотим подключить свой принтер, то нам понадобится реализовать аналогичный интерфейс.
Так что все в ваших руках. Как бы тут зависит многое от того, кем ты хочешь стать. Ремесленником или мастером.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
с помощью которой можно реализовать и инкапсуляцию, и наследование, и полиморфизм
Можно, но далеко не всегда нужно...
 
Можно, но далеко не всегда нужно...
а я и не говорил, что нужно. Речь же идет об актуальности С в 2024. Мой предыдущий пост можно считать аргументом "за".
 
Опять же. Это азы, без понимания которых сложно писать адекватный код. Ну и на собеседовании можно выпендриться :D Главное, чтобы среди оппонентов не оказалось олдскульного Сишника.
 
Си нужно знать вместе с плюсами, два почти идентичные ЯП которые часто используют в связке
Извините, но это бред сивой кобылы. Я про идентичность языков. Между ними примерно столько же общего, сколько между топором и современным деревообрабатывающим цехом. С помощью одного топора можно построить дом, причем если руки откуда надо растут, то он будет ничуть не хуже созданного бригадой мастеров из вышеупомянутого цеха. Да и по скорости разработки профи сможет соревноваться с целой бригадой косорылых мудаков, которые скорее веревкой ногу себе отстрелят, нежели что-то ценное сделают. Но тот же профи, вооружившись современным инструментом и потратив некоторое время на его изучение, будет фактически недосягаем.

Насчет использования в связке. А смысл в чем? Приведите мне пример жизненной необходимости совместного использования, за исключением вызовов системных функций, которые написаны на чистом С.

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

Насчет использования в связке. А смысл в чем? Приведите мне пример жизненной необходимости совместного использования, за исключением вызовов системных функций, которые написаны на чистом С.

Если речь идет о С++, а не о "C с классами".
Спасибо что нашёл время расписать такой текст, но можно это всё уместить в одно предложение которое равноценно наезду. С++ это абсолютно логическое продолжение Си. Конкретный пример нужен? Если ты имел какой либо опыт олимпиадного программирования (более продвинутого чем тупые задачи на вывести а+б). То часто, приходилось писать на Си библиотеках банально потому что они в конкретных задачах могут оказаться эффективными. Пример из реальной жизни: Для быстрого считывания большого объёма данных маленьких чисел я использовал scanf и char(его размер 1 байт). Оно будет эффективнее чем условный short int и std::cin

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

(Про классы я ничего не скзаал, это инной разговор)
 
Последнее редактирование:
Ну майбах тоже логическое продолжение развития телеги. С этим же никто не спорит.
Правда мой посыл был несколько другим, см. мой предыдущий пост о возможностях С. Ну и тем более я не думал, что мое безобидное сообщение будет воспринято как наезд. Упаси боже.
Еще раз. С - это обоюдоострый топор, который требует очень аккуратного обращения и соблюдения техники безопасности. Хороший мастер с его помощью может реализовать все, что угодно за вполне вменяемые сроки. С++ в данном контексте следует рассматривать как навороченный инструмент, которым можно, при желании, забивать гвозде, а можно писать картины. Да, под капотом там будет все тот же топор, но тюнингованный и с его помощью чуть сложнее отрубить себе лишние конечности.

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

Это касается не только плюсов или С, а вообще разработки. Очень многие начинающие и не только погроммисты (не опечатка), понятия не имеют о чистом коде, паттернах, проектировании в целом. Взять любой проект с гитхаба. Половина из них представляют собой откровенный говнокод. Который невозможно читать. Оставшаяся половина тоже оставляет желать лучшего.

Напомню, что большую часть времени программисте не пишет, а читает код. Чужой или свой. От большинства виденного мной кода кровь течет из глаз. Взяь те же исходники конти. С точки зрения функциональности вопросов нет. Видно, что работали грамотные люди. А вот с точки зрения читаемости ... Кстати, это классический пример "Си с классами".

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

В общем, в ближайшее время я начну серию статей по чистому коду и азам проектирования. Возможно и пригодится кому.
 
Ну а вообще, С - это такая штука, с помощью которой можно реализовать и инкапсуляцию, и наследование, и полиморфизм. Правда для этого потребуются небольшие танцы с бубном. Но инкапсуляция в С самая инкапсулированная из всех инкапсуляций.
C:
//point.h
struct Point;

struct Point*makePoint(double x, double y);

double distance(struct Point* p1, struct Point* p2);

//point.c
#include "point.h"
#include <stdlib.h>
#include <math.h>

struct Point {
    double x, y;
};

struct Point*makePoint(double x, double y)
{
    struct Point* p = malloc(sizeof(struct Point));
    p->x = x;
    p->y = y;
    return p;
}

double distance(struct Point* p1, struct Point* p2)
{
    double dx = p1->x - p2->x;
    double dy = p1->y - p2->y;
    return sqrt(dx * dx + dy * dy);
}
Чем не инкапсуляция, в прямом смысле этого слова. Более того, настоящая инкапсуляция есть только в С. В С++ поля класса приходится размещать в заголовчном файле, для того чтобы компилятор мог определить размер экземпляра каждого класса. Про шарп и прочих петухонов я вообще промолчу.

Наследование.

Тут тоже все просто.

Допустим нам понадобилась именованная точка. Значит придется добавить еще одно поле в структуру Point.

C:
//named_point.h

struct NamedPoint;

struct NamedPoint *makeNamedPoint(double x, double y, char *name);

void setName(struct NamedPoint *np,  char* name);

char *getName(struct NamedPoint *np);

//named_point.c


struct NamedPoint
{
    double x, y;
    char *name;
};

struct NamedPoint *makeNamedPoint(double x, double y, char *name)
{
    struct NamedPoint *p = malloc(sizeof(struct NamedPoint));
    p->x = x;
    p->y = y;
    p->name = name;
    return p;
}

void setName(struct NamedPoint *np,  char* name)
{
    np->name = name;
}

char *getName(struct NamedPoint *np)
{
    return np->name;
}

main.c

#include "point.h"
#include "named_point.h"
#include <stdio.h>
int main(int argc, char*argv[])
{
    struct NamedPoint *origin = makeNamedPoint(0.0,0.0,"origin");
    struct NamedPoint *topRigth = makeNamedPoint(1.0,1.0,"topRigth");
    printf("distance = %f", distance((struct Point*)origin, (struct Point*)topRigth));
}
Как бы мы без особых проблем реализовали Наследование. Но данный трюк возможен только в том случае, когда поля и порядок их объявления совпадают у "родительской" и дочерней структур.

С полиморфизмом всё несколько сложнее. Там уже используются указатели на функции. В качестве примера можно привести реализациию ввода/вывода в UNIX, где система драйверов, по сути, реализована в виде плагинов с заданным интерфейсом. Как-то так это будет выглядеть.
C:
//file.h
struct FILE
{
    void(*open)(char *name, int mode);
    void(*close)();
    int(*read)();
    void(*write)(char);
    void(*seek)(int index, int mode);
};


//file.c
#include "file.h"
    void open(char *name, int mode) {/*implementation*/}
    void close(){/*implementation*/}
    int read() {/*implementation*/}
    void write(char) {/*implementation*/}
    void seek(int index, int mode) {/*implementation*/}

struct FILE console = {open, close, read, write, seek};
Немного магии и у нас готова реализациия консолного ввода/вывода.

Если мы хотим подключить свой принтер, то нам понадобится реализовать аналогичный интерфейс.
Так что все в ваших руках. Как бы тут зависит многое от того, кем ты хочешь стать. Ремесленником или мастером.
Роберт Мартин, Чистая архитектура. Если ничего не путаю =)
 
Роберт Мартин, Чистая архитектура. Если ничего не путаю =)
Он самый )
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Всем привет, хотелось бы узнать на сколько актуальна статья. Есть ли смысл изучать в 2024? Вирусы под винду все также пишутся на С? Или появилось что-то новое?
yes , i will learn c in 2028 , c or c++ is a very strong language
 
Спорное утверждение. Лично знаю человека, прорешавшего почти все задачи из четырехтомника "Искусства программирования" Д. Кнута и не попавшего при этом в дурку. Чувак теперь находится на своем месте и занимается любимой работой за очень хорошие деньги.
Тут просто надо очень аккуратно подходить к выбору задачника. Ориентируемся на классику. Для С++ однозначно рекомендую Мейерса.
1) Эффективное использование C++. 55 верных советов улучшить структуру и код ваших программ [2006] Мэйерс.
2) Эффективное использование С++. 35 новых способов улучшить стиль программирования [2006] Скотт Мейерс.
3) Эффективное использование STL [2002] Скотт Мейерс. Несколько устарела, но для понимания основ бытия очень полезна.
4) Эффективный и современный С++ 42 рекомендации по использованию С++ 11 и С++14 [2016] Скотт Мейерс. Очень многие сложные вещи объясняет доступно.
для жавы посоветуешь порядок полезных сборников?)
 
для жавы посоветуешь порядок полезных сборников?)
жаба бывает разная. Если для начинающих, то однозначно Хорстманн и Эккель (Философия джава).
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Насчет использования в связке. А смысл в чем? Приведите мне пример жизненной необходимости совместного использования, за исключением вызовов системных функций, которые написаны на чистом С.
Я пишу на Си, но часть апи от негрософт очень тяжело вызывать с этого самого Си. В основном это COM, разные там gdi+ и т.д. Здесь есть два варианта - или самому писать прототипы, играться с инклудами, или добавить файл .cpp и в нем сделать все в extern 'C' proc
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх