LINUX.ORG.RU
ФорумTalks

C vs. C++

 ,


2

9

Чего такого умеют кресты, что не умеет Си?

Шаблоны - никто не пользует.

Перегрузка операторов - вообще дурь какая-то: не понятно чего ожидать от полюса или минуса.

Очевидный ответ - объекты , а так уж они нужны? Ну вот есть объект - библиотека работы с сокетами. Создал экземпляр, заполнил поля с адресом и портом, выполнил метод connect. Попользовался, освободил память. И чем оно лучше, чем если бы я запилил структуру и набор функций для работы с ней?

За скобки вынесем области применения, где преимущества объектного подхода очевидны: игры, ГУЙ и прочее. Поговорим об остальном.

Перемещено tailgunner из development

★★★★★
Ответ на: комментарий от Freyr69

SPARK - отдельный язык.

frama-c — тоже отдельный язык?

Да, конечно.

Спарк — просто верификатор на SAT+coq

SPARK - это прежде всего набор аннотаций.

Нет ужаса autotools/cmake — уже победа, я считаю.

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

В си++ есть децималс в стандартной либе?

Только в Boost.

В крестах есть только низкоуровневые примитивы, вроде барьеров и атомиков, не?

«Таски, контейнеры, примитивы синхронизации» (STL, нити, мютексы, условные переменные). В Ada, конечно, возможности богаче, но в Си++ тоже есть всё нужное.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Да, конечно.

Нет. Framework for Modular Analysis of C programs — не язык, по крайне мере не язык программирования.

SPARK - это прежде всего набор аннотаций.

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

Saying that something is “in spark” is really just a fancy way of saying “using the subset of Ada 2012 that the spark tools can prove”

мютексы, условные переменные

Ну это все низкоуровневые примитивы, в аде есть таймауты, рандеву (что-то тип месседжей между тасками, это все руками придется городить). [1]

[1] https://two-wrongs.com/selective-delay-in-spark-and-ravenscar

Freyr69 ★★★
()
Ответ на: комментарий от Freyr69

В последнем спарке используются аннотации из ады в основном в триплетах хоара

На этапе компиляции умеет проверять?

anonymous
()
Ответ на: комментарий от Freyr69

Framework for Modular Analysis of C programs — не язык, по крайне мере не язык программирования.

Этот framework == Си + аннотации. За счет аннотаций - это новый язык. То же и про SPARK.

в аде есть таймауты, рандеву

Да, в Ada это богаче. Но я не вижу особых новаций в инфраструктуре по сравнению с Си++.

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от tailgunner

За счет аннотаций - это новый язык.

openmp — новый язык?

Но я не вижу особых новаций в инфраструктуре по сравнению с Си++.

Ну полноценная верификация и ravenscar — это огромный шаг вперед, как по мне. Вообще формальных методов в современном софтописательстве слишком мало.

Freyr69 ★★★
()
Ответ на: комментарий от Freyr69

За счет аннотаций - это новый язык.

openmp — новый язык?

Википедия говорит, что OpenMP - это API.

Ну полноценная верификация и ravenscar — это огромный шаг вперед, как по мне

Конечно. Но называть Ravenscar «инфраструктурой» я бы не стал. AFAIK, так его (и SPARK) никто не называет.

tailgunner ★★★★★
()

RAII, больше ничего нет.

den73 ★★★★★
()

Неймспейсы интегрированы в язык.

cvv ★★★★★
()
Ответ на: комментарий от pihter

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

Может это просто ты не можешь?

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

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

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

vlad9486
()
Ответ на: комментарий от pihter

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

anonymous
()
Ответ на: комментарий от slovazap

Есть стандартная библиотека в которой есть хотя бы строки.

С каких пор std::string стал строкой в полном смысле, а не обёрткой над char*?

RazrFalcon ★★★★★
()

Набросил жидким. Не в плане едкости и консистенции, а по содержательности.

Virtuos86 ★★★★★
()
Ответ на: комментарий от vlad9486

Тут скорее проблема плохой работы c++ с сишными типами. С классами таких проблем нет, а вот когда любые числовые типы неявно кастуются в большие, а generic pointer может быть числом, вот и появляется неточность. Лучше бы оставили для этих случаев принципы работы как в C, когда подходит первый попавшийся вариант перегрузки и когда можно в generic pounter и обратно кастовать неявно указатели. Да, это может привести к UB, но было бы совместимо с C. А в случае перегрузки - всё равно все варианты перегрузки должны давать валидный результат, иначе плохих последствий не избежать, так что требование однозначности просто бесполезное

mittorn ★★★★★
()
Ответ на: комментарий от anonymous

Уже задумывался над этим. Было бы очень неплохо, но придётся городить новые нативные типы - расширять язык. Человек который делал биндинги на lua сталкивался с этим. Или с сишной струетурой придётся работать через оффсеты, или расширять язык

mittorn ★★★★★
()
Ответ на: комментарий от mittorn

Сишные структуры представляются типизированными массивами, обернутыми в объект, с прозрачным доступом к полям.

anonymous
()

И чем оно лучше

не нужно писать лишних 3 строки кода на каждый класс
не нужно писать лишнее слово при инициализации классов

missxu
()

Чего такого умеют кресты, что не умеет Си?

STL же. STL - это прекрасно. STL - это радость. STL - это счастье. STL наполняет нашу жизнь смыслом. STL защищает нас от зла. STL превыше всего.

Хотите поговорить об STL, нашей благодати?

Вы знаете, что STL любит вас?

anonymous
()

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

bvn13 ★★★★★
()
Ответ на: комментарий от FilosofeM

перед тем, как начинать писать на нормальных языках - Kotlin, Java, Ruby, Python, Julia и т.д.

Ух ты, даже питон нормальным стал. Теперь он же круче плюсов. Посравнивай еще.

Deleted
()
Ответ на: комментарий от bvn13

Не парься. Кто ищет, тот найдет ответы на свой вопросы.

Deleted
()
Ответ на: комментарий от pihter

Перегрузка операторов — офигенная вещь. Например, сложение и умножение определено для матриц и векторов, гораздо естественнее написать res = A*x+ B*y + C*z чем

res = add(add(mmul(A,x), mmul(B, y)), mmul(C, z))

Код проще и нагляднее, а значит — меньше ошибок. И это при том, что сами по себе «матрицы» и «векторы» - вполне себе нетривиальные классы с менеджментом памяти, проверкой границ (если надо) и внутренними данными, вроде размерностей.

unanimous ★★★★★
()
Ответ на: комментарий от xmikex

Простым включением структуры базового класса. Например, в ядре линукса struct pci_dev содержит struct device, а struct device содержит в свою очередь struct kobject.

anonymous
()
Ответ на: комментарий от hobbit

#include не парсится компилятором, он просто включает одну простыню текста в другую простыню текста.

И это прекрасно: сразу понятно как оно работает.

В си и крестах при пропущенном #include результат зависит от фазы Луны, поскольку в одной системе простыни из сторонних библиотек могли быть включены друг в друга, а в другой нет.

Ну так это проблема зоопарка систем (стандарт нужен), а не идеи инклудов.

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

Ещё из-за отсутствия модульности приходится применять левые системы сборки, стражи компиляции и др

Зато есть возможность всеми этими процессами управлять

pihter ★★★★★
() автор топика
Ответ на: комментарий от XMs

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

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

Если не станет, то приноси сорцы, будем смотреть, может, ты на плюсах в процедурном стиле пишешь

А в каком еще стиле там писать? В функциональном?

Отталкиваться от ООП далеко не всегда проще. Городить объект «текст» с полями, методами, конструкторами, деструкторами и пр, ИМХО, не проще чем просто набор функций для обработки char*, в том случае, когда я пишу просто программу обработки текста

pihter ★★★★★
() автор топика
Ответ на: комментарий от Deleted

Написано не потому что C лучше сейчас, а потому что тогда ничего лучше не было.

Я вот к чему: можно один раз изобрести бетон, узреть что он хорош и построить всю цивилизацию на бетоне. А можно изобрести бетон, узреть, что он не идеален и лить слезы, что человечество до сих пор использует бетон, несмотря на наличие стопицот материалов, которые всем лучше. Инфраструктура есть под бетон. Бетон работает. Я не говорю, что до скончания времен надо все строить из бетона, я говорю, что на данном историческом этапе, бетон — наше все. А остальное — маргинальщина. Из которой когда-нибудь вырастет бетон++ или даже бетон#, но я вряд ли доживу до дня, когда строить будут из наноиридия, а не из бетона, стало быть, разумно изучать технологии строительсятва из бетона, ибо и сегодня и, очевидно, до конца дней моих, бетон будет стандартом де-факто.

pihter ★★★★★
() автор топика
Ответ на: комментарий от robus

Аргументы по-умолчанию и перегруженные функции — вообще дурь несусветная: не понятно чего ждать от вызова функции

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

Алсо в плюсах есть std::thread, std::chrono, std::optional и куча других приятных вещей. Кроссплатформенне, унифицированне, офигенне.

Да это просто библиотеки, возведенные(?) в стандарт. Этак (с натяжкой) я могу сказать, что в сях есть SDL. Кроссплатформенно, офигенно — все дела.

pihter ★★★★★
() автор топика
Ответ на: комментарий от fornlr

Молодец. Приз 🏆 за самый тупой пост года.

Да все поняли уже, что ты умеешь смайлики вставлять. Несмотря на тупизну

pihter ★★★★★
() автор топика
Ответ на: комментарий от slovazap

За освобождением ресурсов не надо следить потому что RAII

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

Если я правильно понял, то RAII — не механизм языка, а — концепция программирования, которую кресты позволяют реализовать, само-собой оно так не работает, так нужно написать конструктор.

Но, позвольте, я ведь такое и на си могу реализовать. Создаю новый файл .c, объявляю там сколько хочу внутренних (static) переменных, сколько хочу публично-доступных. Объявляю и динамический объект, char*, например. Пишу функцию освобождения памяти (обертку над free), пишу и «конструктор» в котором вызываю alexit(имя_моего_деструктора). Все.

Теперь программисту-пользователю моего класса достаточно только заинклудеть хидер и в любом месте вызвать функцию-конструктор для получения экземпляра «объекта». Я могу и вызывать «методы» объекта, вызывая другие функции из своей библиотеки, передавая дескриптор объекта в качестве параметра.

pihter ★★★★★
() автор топика
Ответ на: комментарий от slovazap

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

Единожды написанные функции-обертки спасут отца русской демократии. И уже написали сто пудов. А если и нет, себе написать h-файлик и назвать исключения.h, который заинклудил (обращаю внимание, ТЫ управляешь процессом: надо — заинклудил, не надо — нет) и можно спокойно пользоваться fopen не проверяя ошибки (за тебя это сделает функция обертка, поведение которой контролируешь ТЫ: хошь она напечатает ошибку и завершит программу, а хошь — запишет в лог и продолжит)

pihter ★★★★★
() автор топика
Ответ на: комментарий от pihter

Вот строят дома из твоего бетона. А затем кто-то подаёт идею что заливать его на железный каркас - в пару раз (Не разбираюсь, на деле число другое) будет прочнее, но ты упёрт и продолжаешь использовать бетон, несмотря на его _объективно_ худшие качества. Если тебе ремонтировать дома из бетона - то да, только бетон. Если строить новые - то железобетон. Это и есть процесс, результаты которого ты хочешь не застать, но который уже происходи и в котором ты не хочешь принимать учаситя, судя по всему. Я к тому что используя C там, где можно обойтись без него ты только тормозишь прогресс (А используя JS где не надо - толкаешь регресс, но это уже совсем другая история) и от этого не будет лучше никому.

Deleted
()
Ответ на: комментарий от slovazap

Есть стандартная библиотека в которой есть хотя бы строки.

Я о чем и говорю: в плюсах есть библиотека для работы со строками и в си есть библиотека функций для работы со строками. И в чем разница? Что там — объект строка и методы к ней, а тут char* и набор функций для работы с ним?

pihter ★★★★★
() автор топика
Ответ на: комментарий от pihter

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

Deleted
()
Ответ на: комментарий от pihter

Напиши код для:
1.Прочитать строку из файла input.txt (Кодировка - UTF-8).
2.Перевернуть.
3.Сделать NFC нормализацию.
4.Записать в output.txt.
На C и не на C, тогда и поймёшь в чём разница.

Deleted
()
Последнее исправление: dearAmomynous (всего исправлений: 1)
Ответ на: комментарий от slovazap

Итого, банальная программа расчёта медианы, описанная на естественном языке как «открыть файл, прочитать из него сколько в нём есть чисел, отсортировать, вывести средний элемент». На C++ будет написана 1 в 1 так же, оставаясь корректной (т.е. с обработкой ошибок, с освобождением утечек и с освобождением ресурсов), на C она разрастётся раз в 10, потому что тебе как минимум нужно будет написать руками вектор на realloc, проверять за каждым вызовом open, malloc, realloc, read код возврата и обрабатывать ошибки, освобождать все выделенные ресурсы, руками парсить содержимое файла и т.д., а потом отлаживать ошибки которые ты во всём этом допустил.

Вот тут разница в подходах: если тебе подавай поближе к человеческому и не париться об ошибках и памяти, нафиг тебе вообще плюсы? Пиши на высокоуровневых, там и к человеческому поближе и запар поменьше. Щас, говорят, есть такое что даже мышкой можно. Мне же нравится чтоб был максимальный контроль, что Я мог все решать, всем управлять и все контролировать. Сделать как нужно МНЕ. Человекоподобности мне не нужно, напротив, получая контроль над всем, я вынужден думать как компьютер, ставить себя на его место и вместе с ним выполнять программу. Взамен за травму мозга я получаю неограниченную влясть над компьютером.

И сейчас даже не обсуждаю сферы, где близость к железу критична (ядра, драйверы, микроконтроллеры), тут преимущества Си над человечным языком неоспоримы, я про просто программы: обработка данных, к примеру. Мне нравится все контролировать, поэтому Си. Может быть я мало заню про плюсы — пожалуй, ну мы это исправим.

pihter ★★★★★
() автор топика
Ответ на: комментарий от slovazap

Подумай головой, как ты без перегрузки операторов будешь работать с комплексными числами, длинной арифметикой, векторами или матрицами. Строить кашу из вложенных вызовов банальных функций сложения-умножения? С перегрузкой ты напишешь a * b + c * d для любых типов объектов, это будет понятный поддерживаемый код в котором не получится допустить ошибку.

Я, если честно, не особо вижу разницу. Ну напиши в две строки:

ad = mult(a, b);
cd = mult(c, d);
x = sum(ab, cd);
ИМХО, читабельность не пострадала, еще и место под комменты осталось. Это притянутый аргумент: этот сахар выглядит на первый взгляд приятно и круто, но на поверку оказывается не нужен. В высокоуровневых языках где можно переопределить все и вся — пожалуй, а в низкоуровневых не столько человечность нужна, сколько близость к машине. А тут, по факту, неявный вызов функции, против явного в аналогичном случае в си.

pihter ★★★★★
() автор топика
Ответ на: комментарий от slovazap

не понятно чего ожидать от полюса или минуса

Это детские страхи. Сами по себе операторы не переопределятся, а там где их переопределили их определили с вполне конкретной целью. А вот в C, напомню, вообще ничего ожидать ни от чего нельзя, поскольку убогость языка фикится макросами, а с ними банальный MIN(a, b) может привести к чему угодно.

Я уже согласился с аргументом что «не понятно чего ожидать от a+b» == «не понятно чего ожидать от sum(a, b)»

Обращу, однако, внимание, что твой аргумент в той же степени справедлив и для макроса MIN(a,b)

pihter ★★★★★
() автор топика
Ответ на: комментарий от vlad9486

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

Может это просто ты не можешь?

прошивки для AVR. высокоуровневых компиляторов нет.(по крайней мере я не слышал): там и на сях-то порой тесно.

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

pihter ★★★★★
() автор топика
Ответ на: комментарий от vlad9486

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

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

Ну вот смотри: задача — сделать мраморную статую. Мы зовем известного мастера, даем кусок мрамора, зубило, молоток и говорим: ТВАРИ!

Тут приходят любители ограничений и говорят: а если он себе зубило в глаз забьет? давайте мы ему маску из стекла бронебойного!

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

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

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

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

pihter ★★★★★
() автор топика
Ответ на: комментарий от vlad9486

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

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

pihter ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.