Главная | Настройки | NSFW
Тема:
Доски


[Ответить в тред] Ответить в тред

[Назад] [Обновить тред] [Вниз] [Каталог] [ Автообновление ] 52 / 10 / 33

Pure Си Anonymous No.1761
Kleinian_group_[...].png (20 KB, 1000x1000)
Первый. Официальный. Си тред.
Рассказываем своё отношение к языку. Делимся программами. Критикуем. Хвалим.
Только чистый Си по заветам старой школы.
Anonymous No.1762
Mathcarbrea.jpg (110 KB, 475x332)
Сразу дискасс.
Могу раскритиковать Паскаль с нескольких сторон:
1. Используется скалярный оператор присваивания. Это напрягает бутылочное горлышко алгоритмической модели фон Неймана.
2. Строгая типизация.
3. Промышленное программирование неудобно за счёт отсуствия внешних библиотек.
4. У Си лучше интерпретируемые компоненты.

А чем плох C?
Anonymous No.1763
Писал на чистом C когда-то прошивки для микроконтроллеров. А программы для пк на чистом C наверное и не пишут сейчас, да?
Anonymous No.1764
image.jpg (33 KB, 310x290)
>>1762
Критиковать Паскаль не имеет смысла, потому что никто и не рассматривает его как вариант при выборе языка программирования. Но если очень хочется, то достаточно вспомнить, что там в функции нельзя массивы произвольной длины передовать, и больше уже ничего говорить не надо.

>А программы для пк на чистом C наверное и не пишут сейчас, да?
Что означает термин "чистый Си"? GCC-вариант, на котором пишут ядра ОС и юзерспейсовые программы под них - считается?
Anonymous No.1765
>>1764
>считается?
Считается.
Anonymous No.1766
>>1761 (OP)
...батя может в си!
Пока это так - всё в порядке на Руси.
Anonymous No.1767
platochik.jpg (6 KB, 277x182)
>>1763
Погуглил.
На С пишут: оси, ПО систем реального времени, драйверы.

>>1764
>нельзя массивы произвольной длины передовать
Это и подразумевал под строгой типизацией.
Anonymous No.1771
Как реализованы передача по результату и передачу по имени в Си?
Anonymous No.1772
1577601512_1577[...].jpg (191 KB, 600x1104)
У меня есть ебанутая мечта, создать Android SDK целиком на Си и под Си, под мобильную разработку, вместо Kotlin/Java. То есть целиком писать код типа
struct {
pointer p,
int size
...
} View

View
v = (void*) setContentView(R.layout.activity_main)

Но как представлю, сколько под эту мечту придется вручную кода написать (да меня еще потом и засрут внутри коммьюнити, что не нужно, и поддерживать тяжело), что даже мечтать боюсь в эту сторону.
Anonymous No.1774
Раньше имел опыт только с питоном.
Попробовал прогать на Си. Думал байтоебить будет сложнее, но нет, мне даже понравилось писать несколько функций и высчитывать байты вместо того чтобы написать одну строку на питоне. Аналогично с отсутствием сборщика мусора.
Но вот чет прижиться к отсутствию ООП я не смог. Капец сколько однотипного кода получается.
Anonymous No.1775
>>1772
AIDL просто заставить делать вывод на Си.
Anonymous No.1776
>>1774
Что тебе мешает городить подобие объектов и включения объектов/наследования на Си?
Anonymous No.1777
>Только чистый Си по заветам старой школы.

Зачем? Я в обще хз в чем его использовать кроме ускорения Питона. Пишу алгоритмы(сортировки в основном) в узких местах пихоновских модулей.

>Рассказываем своё отношение к языку

Костыли при работе со строками, которые костыль над массивами + >>1774
плюсану к однотипному коду, но все же сборщик мусора тут нахуй не нужен. Если нужен сборщик - идёшь в плюсы .
Всё, больше критических претензий к нему нет. Мои задачи он полностью удовлетворяет.
Anonymous No.1778
>>1776
Оче муторно, или я просто не знаю способов.
Anonymous No.1784
>>1761 (OP)
Ужасный ЯП!
Переменные не инициализируются автоматически, нет переопределения операторов, слишком много бойлеблейта.
Пишу на си уже больше трёх лет.
Anonymous No.1785
>>1777
> Если нужен сборщик - идёшь в плюсы .
Он там разве есть?
Anonymous No.1786
>>1784
>переопределения операторов
Что ты имеешь ввиду? Ты же в локальном блоке можешь её переопределить.
Anonymous No.1787
>>1786
Я имею ввиду перегрузку операторов. Чтобы можно было комплексные числа или вектора складывать не через vector = VectorAdd(v0,v1), а с через vector = v0 + v1.

Ещё в си нельзя сделать значение по умолчания для аргумента функции (как в питоне), из-за чего может быть ещё больше бойлерблейда.
Anonymous No.1788
>>1787
Вот про перегрузку удваиваю - почему бы просто не добавить перегрузку функций, операторов и статические методы (без наследования и прочего ооп мусора), чтобы это был просто синтаксический сахар. Это же требует минимум модификации компилятора - потому что внутри это всё те же функции вызывающиеся обычным способом, только функция чуть-чуть менее явно указывается.

>Переменные не инициализируются автоматически
Бесполезный мусор. Если они инициализируются автоматически, то программа делает лишние действия даже когда тебе это не надо. Сейчас же можно тривиальным образом их инициализироовать только когда это необходимо.
Anonymous No.1789
8df2daf53dd978d[...].jpg (132 KB, 728x754)
>>1787
Справедливости ради, комплексные числа есть в Си и работают с обычными арифметическими операторами.

>>1788
А мне вот наоборот было бы неприятно знать, что привычный оператор может неявно какую-нибудь функцию мне вызвать. (Кроме того, перегрузка операторов требует наличия исключений в языке, потому что иначе как сообщить программе об ошибке?)

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

>Сейчас же можно тривиальным образом их инициализироовать только когда это необходимо.
Или забыть это сделать и получить ундефайнед бехавиор из-за оптимизаций, которые наделал компилятор.
Anonymous No.1790
image.png (5 KB, 322x372)
>>1789
>неявно какую-нибудь функцию мне вызвать
В моей ide любые перегруженные операторы подчёркиваются. И скорее всего в любой другой тоже можно так сделать.

>перегрузка операторов требует наличия исключений в языке
Поясни? Какое исключение может быть при сложении двух чисел? Никакого. Если твоя перегрузка такая, что в ней может быть ошибка, то мне это видеться идеалогически неправильной перегрузкой.
А ещё можно сделать так, что c=a+b эквивалентно add(a,b,c), где c передаётся по указателю (или ссылке), а передачу по значению в перегрузках слишком сложных типов запретить. Если происходит ошибка, то состояние объекта c не изменяется, и всё. Если перегрузки передают результат по значению, то они должны во всех случаях работать без ошибок, на уровне сложения чисел.
Я вообще в осадок выпал от чуши, которые нагородили в новых стандартах крестов по поводу исключений и noexcept-ов, и ещё в каждом меняют всё с ног на голову.


>Или забыть это сделать и получить ундефайнед бехавиор из-за оптимизаций
Можно пример, в каком случае будут виноваты оптимизации?
Если ты читаешь и используешь значение неинициализированной переменной - то это не ud, это ты стреляешь себе в ногу. С тем же успехом можно читать сегмент на харде и использовать его значение для чего-то, только вместо харда память.
Anonymous No.1794
image.png (309 KB, 514x431)
>>1790
>В моей ide любые перегруженные операторы подчёркиваются.
Охуенно, не знал о такой фиче.

>Какое исключение может быть при сложении двух чисел? Никакого.
Если ты складываешь два числа по сети, то у тебя может быть ошибка соединения.

>Если твоя перегрузка такая, что в ней может быть ошибка, то мне это видеться идеалогически неправильной перегрузкой.
Это сильно ограничивает область применения перегрузки. Почему бы не позволить с её помощью делать операции не только с числами, но и векторами, матрицами, какими-нибудь ещё математическими объектами?

Если у тебя есть два объекта, между которыми не всегда можно осуществить операцию сложения, и проверить это можно только в процессе выполнения операции. Или даже просто деление матрицы на другую матрицу - ты узнаешь, что это невозможно сделать только в процессе. И как сообщить об этом? Инициировать прерывание как при делении на 0? Возвращать NaN, чтобы оно по-тихому сломалось и продолжило работать, только неправильно? Оба варианта - полный отстой.

>А ещё можно сделать так, что c=a+b эквивалентно add(a,b,c), где c передаётся по указателю (или ссылке), а передачу по значению в перегрузках слишком сложных типов запретить. Если происходит ошибка, то состояние объекта c не изменяется, и всё.
Ну охуеть, а если оно может не измениться и в результате корректной операции? Как отличить это от ошибки? Ошибки нельзя замалчивать, их надо обрабатывать. Современные языки типа Го и, кажись, Раста, не позволят тебе идти дальше, пока ты код для обработки ошибки не добавишь.

>Можно пример, в каком случае будут виноваты оптимизации?
Вообще, неопределённое поведение возникает, когда пользователь читает неинициализированную переменную. Оптимизации только обеспечивают более неприятные последствия.

>Если ты читаешь и используешь значение неинициализированной переменной - то это не ud, это ты стреляешь себе в ногу. С тем же успехом можно читать сегмент на харде и использовать его значение для чего-то, только вместо харда память.
Если ты думаешь, что результат чтения неинициализированной переменной - это просто мусорное число, то ты ошибаешься.

Что напечатает эта программа?

#include <stdbool.h>
#include <stdio.h>

static bool condition = false;

int main(void) {
int x;

if (condition) {
x = 7;
} else {
printf("%i\n", x);
}

printf("%i\n", x);
}


Спойлер: на GCC 9.2.0 с оптимизацией -O3 печатает: 0, затем 7. Как это объяснить?
Anonymous No.1795
Я не особо въехал в хаскель, но мне понравилось что операторы это те же функции, только пишутся по середине, для удобства. Имхо так и должно быть сделано, зачем разделять
Anonymous No.1796
image.png (18 KB, 694x318)
>>1794
>И как сообщить об этом?
Если может произойти ошибка, то в объекте должна быть переменная с флагом ошибки, и тебе нужно проверять объект на наличие ошибки после каждой операции. c=a+b; if (c.error()) {...} или if(add(a,b,&c)) {...}
Исключения - раковая идея для языка не слишком высокого уровня, почти никто (я) не понимает как они должны работать, даже эти типы разрабатывающие кресты не могут определиться несколько стандартов вроде как.

>Спойлер
Не удивил, если честно, даже с -O1 работает. Ты не определил значение переменной, компилятор видит что её значение нигде не указывается - потому в действительности переменной не существует, для неё и строчки x=7 просто нет кода, а компилятор ставит те числа, которые ему удобно в плане быстродействия или времени компиляции.
Если тебе в действительности нужна реальная переменная, чтобы программа считывала ячейку памяти вместо подстановки числа, то можно volatile поставить, вроде бы он для того и нужен.
Если ты предлагаешь прикрутить нечто вроде volatile всем по умолчанию, то во всех случаях где можно было бы обойтись вовсе без переменных компилятор будет их создавать, что не очень хорошо скажется на быстродействии.
И для чего это нужно? Такое может потребоваться, только если ты пишешь что-то типа такого, что сработает лишь на одном компиляторе:
volatile int x,y,*e;
e=&y;
e[-1]=15; //при -O3 печатает 15
e[+1]=19; //при -O0 печатает 19
printf("%i\n", x);



Потрогал перегрузки - очень неинтуитивная штука (в плане передаче по ссылкам, rvo и где и в каком месте используются конструкторы копирования/перемещения или соответствующие операторы присваивания). Вот бы статью или главу в книги про них найти.
Anonymous No.1797
>>1788
Нее, перегрузка функций это фу. Когда я буду либу через libdl загружать, как мне понять, какую именно я загружаю?
>программа делает лишние действия даже когда тебе это не надо
Переменные должны иницаилизироваться всегда! Вопрос в том, сделать это компилятору или программисту и во втором случае компилятор может просканировать функцию на наличие записи до чтения, чтобы понять, что не надо инициализировать.
>>1789
>иначе как сообщить программе об ошибке?
лолвут, сегфолт просто устроить и будет сообщений об ошибке в дебаггере.
С такой логикой можно сказать, что написание функций требует наличия исключений, иначе как сообщить программе об ошибке.
>>1794
Если так сильно нужны исключения для редких функций, то можно и setjmp/longjmp обойтись.
Anonymous No.1799
>>1797
>Переменные должны иницаилизироваться всегда!
Принципиальное непонимание назначения и философии языка.

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

У вас имеется буфер (массив) который вы используете в цикле приема данных. Зачем его предварительно чем-то инициализировать, если он все равно будет заполнятся новыми данными несколько раз?

У вас есть указатель, который будет инициализирован адресом в момент вызва функции выделения памяти с последующей проверкой значения. Зачем его предварительно инициализировать, если он по любому не может быть использован до момента вызова функции выделения памяти?

У вас есть переменная для хранения временного значения, зачем ее предварительно чем-то инициализировать, если она по логике алгоритма обязана принимать актуальное значение перед использованием?

>Вопрос в том, сделать это компилятору или программисту и во втором случае компилятор может просканировать функцию на наличие записи до чтения, чтобы понять, что не надо инициализировать.

Компилятор и так выдаст ошибку в случае попытке использования в неком вычислении неинициализарованной переменной. Не надо путать "создание и предварительную инициализацию" переменных в языках высокого уровня, которая по любому включает дополнительные действия и требует процессорных ресурсов (манипуляции с памятью, создание необходимых служебных структур данных и т.д.) и переменных в низкоуровневых языках, которые представляют собой области памяти в сегменте данных, куче или стеке.
Anonymous No.1800
>>1799
Я же и написал, компилятор сам оптимизирует, нужно ли ему лишний раз инициализировать переменную или нет.
>Компилятор и так выдаст ошибку в случае попытке использования в неком вычислении неинициализарованной переменной
У меня не выдавал.
Anonymous No.1801
>>1800
>У меня не выдавал.
Быть такого не может. Какой компилятор? С какими параметрами? Пример кода в котором он должен выдававть предупреждение, но не выдает.
Anonymous No.1802
>>1801
Ну хоть этот
#include <stdio.h>
#include <math.h>

int main() {
int a;
float b = sin(a);
printf("%f\n",b);
}

Что gcc, что clang с параметрами test.c -o test -lm не выдаёт предупреждения. Когда-то из-за этого у меня были большие баги. Теперь я использую cppcheck.
Anonymous No.1804
>>1802
>не выдаёт предупреждения
Ясное дело, что компилятор не выдает ничего, когда вы его об этом не просите.
Всегда используйте ключ -Wall включающий вывод таких сообщений, а лучше используйте make - даже для проектов состоящих из одного файла, и занесите в Makefile все параметры компиляции.

Кроме того дополнительно стоит указывать сам стандарт языка которому соответствует ваш код, например: -std=gnu99.

gcc -Wall -std=gnu99 -o test test.c -lm

Кроме -Wall, имеется ключ -Wextra, который выводит расширенный список предупреждений. Как же не любят люди читать документацию, а потом имеют большие баги и тратят время на их устранение.
Anonymous No.1805
>>1802
>cppcheck
Очень рекомендую изучить и всегда использовать для проверки корректности работы с динамической памятью valgrind.
Anonymous No.1822
>>1761 (OP)
Посоветуйте книги по С11.

Макград 16 года, но там не указан стандарт
Некоторые функции и его реализации не работают
указывается что они устарели
Anonymous No.1871
>>1822
Почему не С18?
Anonymous No.1872
>>1871
Почему не С99?
Anonymous No.1873
>>1872
Время движется, стандарт развивается. Логичнее, по идее, использовать новейшую из доступных версий, если нет противопоказаний. А судя по тому что >>1822 только начинает, противопоказаний пока не возникло.
Anonymous No.1874
>>1873
>Время движется, стандарт развивается.
Почитаете сначала про отличия между С18, С11 и С99. Хотя бы здесь: https://en.wikipedia.org/wiki/C_(programming_language)

После чего, надеюсь, у вас появистя понимание, что самой актуальной версией для базового изучения начинающими на данный момент по прежнему остается C99.
Anonymous No.1875
Пробовал Си. Охуел с того что даже тупа список изменяемого размера надо самому мутить, например через связанный список. В то время как в c++ уже есть std::list и std::vector из коробки. Причём если я правильно понимаю всё что можно сделать си можно сделать и в си++. Ну и какой смысл в Си? Типа сморити я труъ программист?
Anonymous No.1876
>>1875
C это C++ без плюсов. В нём нет ничего такого, чего нет в C++. Не знаю чего ты ожидал.
>Ну и какой смысл в Си?
В отличие от C++ C делает только то, что ты явно напишешь. Там нет множественного наследования, RAII, виртуальных методов или исключений - соответственно почти нет возможности написать плохой код.
Anonymous No.1877
>>1876
>В отличие от C++ C делает только то, что ты явно напишешь. Там нет множественного наследования, RAII, виртуальных методов или исключений - соответственно почти нет возможности написать плохой код.
Чет не понимаю как второе следует из первого.
Anonymous No.1878
>>1875
>Охуел с того что даже тупа список изменяемого размера надо самому мутить, например через связанный список.
Для того, что бы ты мог выбрать и использовать любой алгоритм, реализиующий список, максимально подходящий и оптимизированный именно под твою конкретную задачу, а не навязывать тебе некую обобщенную, универсальную реализацию, покрывающую некие среднестатистичекие требования, которая не будет равно эффективной для всего круга задач ее применения.

>Ну и какой смысл в Си?
С - это в первую очередь - про эффективность кода, а не про удобство его создания. Для удобства стоит использовать высокоуровневые языки.
Anonymous No.1880
>>1878
Выбрать можно везде. Только вот для си я даже не нашёл например либы с контйенерами живой. Глиб не в счёт.
>С - это в первую очередь - про эффективность кода, а не про удобство его создания
Но ведь С++ имеет ту же скорость исполнения, не? С таким же успехзом можешь писать си код, с минимальными измениями, но зато где охуенная эффективность не нужна (а она нужна только в боттлнеках) не надо так сильно ебаться
Anonymous No.1882
>>1880
>Выбрать можно везде.
Подскажи, как, например, в жабоскрипте, пыхе или питоне (любом ЯП, не предоставляющим возможности прямой работы с памятью) ты сможешь задействовать альтернативные алгоритмы работы с данными, не используя встроенные? При этом - напрямую, без интерфейсных прослоек - которые сведут на нет все старания.

>С таким же успехзом можешь писать си код, с минимальными измениями
Ты серьезно считаешь, что C++ код писать (и понимать) проще, чем C? Или предлагаешь заниматься извращениями, пиша плюсовый код в стиле C? С и плюсы - разные ЯП с разными принципами подхода к созданию программ.

>где охуенная эффективность не нужна
Там используется ЯП высокого уровня.
Anonymous No.1883
>>1882
>без интерфейсных прослоек - которые сведут на нет все старания.
Каким образом?
>Или предлагаешь заниматься извращениями, пиша плюсовый код в стиле C?
Каким образом это извращение? Почти любой код С валиден в С++. В конце концов, С++ добавляет фичи к С, но не удаляет. Он лишь даёт новые возможности. Каким же это образом не использовать какие-то возможности в нём это извращение, а в его урезанной версии где их и нет - не извращение?
Anonymous No.1884
Какие вещи для тренировки написать на Си?
Anonymous No.1885
>>1883
>Каким образом?
Ты знаешь про так называемое "внутреннее представлениме данных" в ЯП высокого уровня и принципы размещения и инициализации и сколько служебных оперций (не связанный напрямую с исходной программой) производится при этом?

>Почти любой код
>Он лишь даёт новые возможности
Да, да... Зубило - таже отвёртка только с новыми возможностями. А в автобусе можно возить дрова. Никаких извращений.
Anonymous No.1886
>>1885
>Ты знаешь про так называемое "внутреннее представлениме данных" в ЯП высокого уровня и принципы размещения и инициализации и сколько служебных оперций (не связанный напрямую с исходной программой) производится при этом?
Ок, только как это относится к возможности выбрать алгоритм? Это относится к общей скорости исполнения. В компилируемых языках она примерно равна на самом деле.
> Да, да... Зубило - таже отвёртка только с новыми возможностями.
Нет обратной совместимости
> А в автобусе можно возить дрова.
Тоже нет.
Anonymous No.1887
>>1884
Хорошо бы знать с какой целью изучаешь и какую платформу и ось исползуешь.

Под Linux x86* мог бы рекомендовать сделать модель HTTP сервера. Поможет разобраться с вводом-выводом, сокетами, событийныйми моделями, сигналами, потоками, понятиями: блокировка, асинхронность.
Anonymous No.1890
300px-Mike_Wazo[...].jpg (10 KB, 300x272)
Ок допустим мне нужен ассоциативный массив. Пока варианты
1) Зависеть от огромнейшего glib который ещё и не линкуется статически
2) Брать какой-то там древний sglib который помоему нигде и не используется
3) Писать самому (сирьёзна блять?)
Что делать?
Anonymous No.1891
>>1890
Писать самому, конечно же. Свои велосипеды лучше знаешь, чем чужие.
Anonymous No.1892
>>1891
Язык существует 50 лет. Ассоциативный массив пиши сам. Вообще охуеть.
Anonymous No.1893
Не ну как бы асс. массив довольно часто нужен, это что получается каждая программа таки либо зависит от глиб либо его сама реализует? Также и просто со списками изменяемой длины.
Anonymous No.1894
>>1890
>Зависеть от огромнейшего glib
Не судьба поискать другую либу? Например: https://github.com/troydhanson/uthash

>Брать какой-то там древний
Как качество кода может зависить от его "древности"? Код работает? Покрыт тестами? В чем тогда проблема? Тем более, зачем тебе вся либа? Возьми только требуемую ее часть.

>Писать самому
Возьми код из существующей либы.

>>1892
Забудь о C. Он не для тебя.

[Назад] [Обновить тред] [Вверх] [Каталог] [ Автообновление ]
52 / 10 / 33

[Ответить в тред] Ответить в тред

15000

Ответ в тред No.1761
Настройки
Избранное
Топ тредов