LINUX.ORG.RU

Будущее g++

 ,


0

2

Привет. Были разговоры, что шланг заменит ГЦЦ. Вот смотрю на g++, он активно пилится, оперативно внедряются всякие плюшки из новых стандартов, не похоже как-то на агонию. Может мне не повезло, но для крестов я так и не встретил ни одной нормальной tag системы, а кодить без неё удовольствие сомнительное. Шланг решил эту проблему, дав возможность комфортного, крестового кодописания. Вопрос - зачем нужен g++, если рядом должен быть установлен Шланг? Зачем вообще gcc тратит силы на g++, может лучше вообще забросить и отдать кресты в руки шланга? Просто интересно, ведь пилить компилятор - не самое простое занятие, да ещё и бессмысленное учитывая то, что g++ без шланга неполноценен. О чём они там в ГЦЦ думают? Может я просто не умею голый g++ (без шланга)?

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

Это вопрос из разряда - «Зачем жить, зачем что-то делать?». Множество ПО в том же онтопике продолжают писать на С, да возможно это какое-то нездоровое фанбойство вокруг языка С, но с другой стороны почему бы и нет, тем более что вполне возможно писать довольно качественный софт и на нем. В общем-то, дело тут даже не в этом примере с экзотическими архитектурами.

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

да возможно это какое-то нездоровое фанбойство вокруг языка С

This.

Также часто от поклонников Си слышу, что C++ слишком сложный и в нём много лишнего, но никто не заставляет использовать все его возможности. В coding style можно прописать какими фичами можно пользоваться и как. Ещё есть вариант, что компиляция C++ слишком медленная, но она становится медленной от использования определённых фич вроде сложных вложенных шаблонов, которые также никто не заставляет использовать. Многие фанаты пишут не на Си, а на GNU Си, в котором полно нестандартных расширений, часть которых была здесь представлена.

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

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

Даже самая отвратительная реализация строк, вроде соверменного std:string, подразумевающего оперирование ссылкой на мутабельный массив байт, все равно по уровню безопасности выше Си, потому что нужно знать «какие у него слабые места в этой реализации» чтобы написать ошибку — а в Си ничего не нужно знать, чтобы просто писать ошибки без задней мысли.

время жизни и мутабельность сделали синтаксическим сахаром, а точнее квалификаторы для работы с ними, борроучекер засунули как часть языка, но если честно я не смотрел как конкретно он туда засунут учитывая что это фронт для llvm, засунут он туда явно не сильно глубоко

Проверка оббластей видимости делается на уровне фронтенда, бэкэнд-LLVM уже оперирует опасными сущностями.

в большинстве случаев в зависимости от того чего вы желаете, достаточно
U bar (const T* const foo)

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

Динамические строки паскаля на проверку оказались сишкой под пудрой, такие же реализуются на С

Удачи реализовывать эти строки на Си: Будущее g++ (комментарий)
Ты бы хоть сразу конкретно отвечал, а то какие-то размытые фразы кидаешь.

Все именно так, безупречности там нет, все тоже самое реализуется средствами С. Разница лишь в том, что в ваших условно «безупречных» языках, эту реализацию уже написали

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

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

В чистом Си принципиально нельзя нормально реализовать строки хотя бы потому, что там нет RAII. Есть __attribute__((cleanup (cleanup_function))), но это не часть стандарта

Даже с RAII есть проблема с присвоением динамических структур, даже если мы всегда копируем данные при присвоении. А copy-on-write — это уже просто космос.

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

RAII в С:

#define USING(a, b, c)  \
     for (bool _flag = true; _flag; _flag = false) \
     for (a; _flag && (b); c, _flag = false)

int fun(size_t m) 
{
    int result = -1;
    USING(int* f1 = (int*)malloc(sizeof(*f1)), (NULL != f1), free(f1)) 
    {
       return 2;
    } // ресурс освобождается, вызывается free.
    return result;
}

Твой ход. Так-то при линейном выполнении я могу просто написать «free(f1);» — зачем мне еще какие-то макросы?

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

добавляем ifdef и код компилируется везде

А толку, если код работает неправильно?

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

но по сути МС всегда делали в первую очередь компилятор С++, а не С, С там в нагрузку

А по моим ощущением Си у MS очень даже достойный. Другое дело, что последние несколько лет он не занимается толком ни Си, ни C++, а переключился на .NET и облачные технологии.

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

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

Будто в C++ они не выглядят странно, страшно, и ненужно.

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

Даже самая отвратительная реализация строк, вроде соверменного std:string, подразумевающего оперирование ссылкой на мутабельный массив байт, все равно по уровню безопасности выше Си,

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

потому что нужно знать «какие у него слабые места в этой реализации» чтобы написать ошибку — а в Си ничего не нужно знать, чтобы просто писать ошибки без задней мысли.

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

Проверка оббластей видимости делается на уровне фронтенда, бэкэнд-LLVM уже оперирует опасными сущностями.

Так я про это и написал, просто я не проверял этого лично, что-то как-то лень копаться в расте чтобы это подтвердить.

… и потерять возможность оптимизации кода, потому что компилятор далеко не всегда может угадать, что у тебя в коде на самом деле применяется передача по ссылке, а не передача указателя. И я напоминаю, что хранение промежуточных значений в регистрах, в том числе при инлайне функций — это 90% вообще всего эффекта оптимизации, производимого современными компиляторами.

Приведите примеры, у меня допустим на годболте при -O3 генерируется совершенно одинаковый код для U foo (const T* const bar) и для U foo (const T& bar) наполнение естественно одинаковое. За T брал std::vector. Насколько я помню инлайнинг это вообще шляпа уровня просьбы от компилятора, но он уже сам решит может он это сделать или нет.

Удачи реализовывать эти строки на Си: Будущее g++ (комментарий) Ты бы хоть сразу конкретно отвечал, а то какие-то размытые фразы кидаешь.

Даже нет нужды реализовывать это уже все сделано в С++, и либах на С которые каждый городит свои защитные будки на массивы и строки в стиле С и функции работы с такими будками.

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

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

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

Твой ход. Так-то при линейном выполнении я могу просто написать «free(f1);» — зачем мне еще какие-то макросы?

Можете, но это так же справедливо и для RAII в с++, да и вообще для всего чего угодно, вы вообще можешь делать все что хотите, нет еще такого языка который запрещает вам что-то делать, кроме как просто не скомпилировать очевидно опасный и нерациональный код. Лучше расскажите для чего вы будете делать free(f1) если вы написали подобный код чтобы не делать высвобождение вручную, это какой-то странный способ на зло мамке уши отморозить или что подразумевается под этим действием?

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

Это норм. Не будет работатью

Но у функции должен быть один return. И тогда будет работать.(goto тоже запрещены)

Так-то при линейном выполнении я могу просто написать «free(f1);»

Затем чтобы писать «деструктор» при объявлении переменной, а не где-то далеко в коде. (вместо malloc и free там могли бы быть fopen и fclose) для повышения читабельности.

Вообще мне понравилась эта лекция: https://www.youtube.com/watch?v=SFv8Wm2HdNM

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

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

Можете, но это так же справедливо и для RAII в с++

В C++ деструкторы вызовутся, если сделать return из середины функции или произойдёт исключение. А в коде fsb4000 - нет.

X512 ()
Ответ на: комментарий от fsb4000

Но у функции должен быть один return.

В таком коде будет много вложенных if’ов и он может быть трудночитаемым.

X512 ()
Ответ на: комментарий от byko3y

В MS скоро будет С11(С18) компилятор. По крайней мере точно раньше, чем выйдет Visual Studio 2021.

Уже есть поддержка _Generic макросов:

https://imgur.com/a/Ho6dHVs

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

Так ничто не мешает ему вручную деструктор шлепнуть раньше, такие же результаты будут (в этом и прелесть нашлепок в виде с++, они ни от чего не спасают, они запудривают и говорят вам - «пользуйтесь вот этим видом публичного интерфейса, не пытайтесь использовать нашу пудру так, как ее не предполагалось использовать»), исключения часть ртл, они отключаются т.е. частью языка они не являются это пришитый функционал. «А в коде фбс нет» потому что это не продакшен код, а просто минимальный пример того, что что-то типа RAII можно и на С состряпать, его как минимум можно обернуть адт и написать документацию по использованию и получите приблизительно библиотечную реализацию с++, ну и вы хотите от С того чего он не умеет, eсть заглушки __try, __except, __finally (excpt.h), есть возможность поюзать исключения от с++, но все это противоречит языку, да и в конце концов вы так говорите, как будто исключения это не рантайм механизм, тут только грамотный линтер или статический анализатор могут сказать что вы делаете какую-то дичь, если вы реально ее делаете и не отдаете себе отчет в этом. Ну и как уже писалось выше сначала вы пишите код подобный тому что написан, а потом берете и ломает его работу, классическое ссзб.

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

деструктор шлепнуть

прелесть нашлепок в виде с++

Что значит «шлепнуть» в данном контексте?

__try, __except, __finally (excpt.h)

Нестандартные расширения MSVC.

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

Вызвать деструктор вручную, почему нет.

так они есть и в мингв например, они есть и gnuc, они есть везде где кодовая база это с и с++

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

Вызвать деструктор вручную, почему нет.

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

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

Какая неожиданность, не нельзя, а чревато последствиями, как и вызов free().

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

В отличии от free(), деструктор обычно не нужно вызывать вручную.

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

о чем и речь «обычно» вам навязали интерфейс и соглашения, можете навязать такой же интерфейс и соглашения в С.

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

можете навязать такой же интерфейс и соглашения в С.

Нельзя, всегда будет дополнительная писанина, которой нет в C++ и в которой легко совершить ошибку при написании кода.

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

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

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

Есть функционал, который невозможно реализовать в стандартном Си без дополнительной писанины в каждом месте использования, но можно в стандартном C++, например RAII (как показал byko3y, решение fsb4000 не работает), исключения, подсчёт ссылок, полиморфизм без накладных расходов и с проверкой типов во время компиляции.

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

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

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

отсутствии синтаксического сахара в С это будет выглядеть страшненько

Ну и зачем Си без C++ тогда нужен? Мазохизм? 8 битные микроконтроллеры (что в общем то тоже мазохизм)? Чистый Си уже давно пора закопать.

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

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

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

никакие абстракции ни от чего не спасают

Не спасают, но понижают вероятность совершить ошибку.

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

понижают, но тоже самое и на С можно сделать.

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

Во первых, это надо делать и появятся over 9000 альтернативных реализаций, несовместимых друг с другом. Во вторых, сделать тоже самое на Си не повышая вероятность совершения ошибки нельзя. «будет выглядеть страшненько» тоже влияет на вероятность совершения ошибки.

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

Я лишь отстаиваю точку зрения что никакие абстракции ни от чего не спасают

зачем же тогда придумывают эти «абстракции», раз они «ни от чего не спасают»?..

Тезис же не в том, что в любом ЯП можно отстрелить себе что-нибудь (в целом, это скорее всего так), а в том, что в C это сделать не просто, а очень просто. А вот в C++ уже сложнее (если не писать на нём в стиле С).

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

понижают, но тоже самое и на С можно сделать.

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

Если рассуждать в твоём духе, так любой ЯП можно назвать лишь «абстракцией» над ассемблером.

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

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

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

С развивается, может не так быстро как хотелось бы

А куда ему развиваться?

вот и все преимущество

Этого мало? У меня создаётся впечатление, что чистый Си продвигают старпёры, которые не осилили C++ и других языков и вопят повсюду с религиозной уверенностью: это же язык системного программирования! Это сакральное знание!

X512 ()
Ответ на: комментарий от Sahas

понижают, но тоже самое и на С можно сделать.

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

Если рассуждать в твоём духе, так любой ЯП можно назвать лишь «абстракцией» над ассемблером.

Уже все что надо написано, уже ничего делать не надо, уже есть с++ и за любой яп это по сути наслоение абстракций над «ассемблером» а точнее над форматом записи исполняемого файла для ос и машкодами, спорить с этим бесполезно, яву нельзя сделать иначе.

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

Уже все что надо написано, уже ничего делать не надо, уже есть с++ и за любой яп это по сути наслоение абстракций над «ассемблером» а точнее над форматом записи исполняемого файла для ос и машкодами, спорить с этим бесполезно, яву нельзя сделать иначе.

это сарказм, да?.. :)

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

Справедливости ради, у С есть преимущество в том, что его ABI более-менее стандартизировано и универсализировано, в отличие от того же C++, где каждый компилятор лепит свои несовместимые ABI...

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

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

Этого мало? У меня создаётся впечатление, что чистый Си продвигают старпёры, которые не осилили C++ и других языков и вопят повсюду с религиозной уверенностью: это же язык системного программирования! Это сакральное знание!

Какой раз нужно сказать что я его не продвигаю, я говорю лишь о том, что от «условного С» никуда не убежать, а так что С что С++ дрянь редкостная, как и все программирование в общем-то :D. Этого не много и не мало, это естественное итеративное развитие языков и вообще проектов. Написали один раз, поюзали, поняли что написали херню, начали переписывать, написали получше с учетом тех ошибок и неудобностей что были допущены ранее, снова поюзали, снова поняли что можно было лучше и так по кругу. Забавно что идеальной реализации не достичь никогда, потому что условия использования меняются, можно лишь вывести какие-то средние подходы которые хорошо работают на типичных случаях.

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

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

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

Во-первых: С++ ABI тоже меняется крайне редко.

Во-вторых: для использования С ABI не нужен С. Пиши хоть на Rust, хоть на D, хоть на С++, только помечай функции extern «C» и всё…

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

С есть преимущество в том, что его ABI более-менее стандартизировано и универсализировано

Это ABI не Си, а целевой архитектуры, при компиляции других языков программирования (Pascal, Oberon, Go, Rust) используется то же ABI.

в отличие от того же C++, где каждый компилятор лепит свои несовместимые ABI…

Есть Itanium C++ ABI, которое реализовано в GCC с 2001 года. По сути есть всего 2 ABI: Itanium C++ ABI и Microsoft C++ ABI, причём в Windows также можно использовать Itanium C++ ABI.

Я делал проект, который напрямую использует Itanium C++ ABI на другом языке без прямой поддержки компилятора и всё необходимое работает, включая наследование, dynamic_cast и type_info.

X512 ()
Ответ на: комментарий от fsb4000

С++ ABI тоже меняется крайне редко.

ага, в пределах одного компилятора. Но уже компиляторы MSVS и GCC дают несовместимые ABI

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

Есть Itanium C++ ABI, которое реализовано в GCC с 2001 года. По сути есть всего 2 ABI: Itanium C++ ABI и Microsoft C++ ABI, причём в Windows также можно использовать Itanium C++ ABI.

Это, конечно, здорово. Только вот попытка прикрутить библиотеки, собранные под MSVS, к проекту, собираемому MinGW, у меня окончилась фэйлом...

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

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

Адепты системного программирования это не примут. C++ и Objective C тоже развивались как добавление нового функционала в Си, но стали новыми языками. Будет новый Си-совместимый язык.

X512 ()
Ответ на: комментарий от Sahas

Только вот попытка прикрутить библиотеки, собранные под MSVS, к проекту, собираемому MinGW, у меня окончилась фэйлом…

Она и не могла закончиться чем-то другим. Надо выбрать одну экосистему (GCC/Clang vs MSVC). В рамках экосистемы бинарная совместимость сохраняется.

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

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

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

Модули и пространства имён могут потребовать манглинг, что тоже может встретить сопротивление.

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

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

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

Так сколько же можно одно и то же говорить stl реализация это не строки в языке, это прибитая сбоку либа. Берите либу для которая оборачивает и делает массивы и строки на С безопасными и тогда можно говорить о каком-то сравнении

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

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

Для того, чтобы корректно работать с паскалевыми или стандартными крестовыми строками, мне достаточно быть полным дауном и ничего не знать про то «как задумывалось ее поведение», и в 96,28% случаев я получу очевидное поведение программы, которые может и отличаться от требуемого, но все же быть простым и ясным. Работа с динамическими структурами в Си — это всегда ходьба по минному полю, для которой обязательно нужно тщательное знание карт и методик, иначе ты гарантировано подорвешься, без шансов.

Приведите примеры, у меня допустим на годболте при -O3 генерируется совершенно одинаковый код для U foo (const T* const bar) и для U foo (const T& bar) наполнение естественно одинаковое. За T брал std::vector. Насколько я помню инлайнинг это вообще шляпа уровня просьбы от компилятора, но он уже сам решит может он это сделать или нет

Это правда. Также правда, что компилятор генерирует тот же код для «U foo (T& bar)» потому что он не может быть уверен, что какой-то внешний код не изменит «bar». Также правда, что оптимизация указателя некорректна, и приводит к таким замечательным багам, как:
https://gcc.godbolt.org/z/fWda68

#include <cstdlib>
#include <iostream>
 
struct X {
  int i;
  int j;
};
 
int foo(struct X *p, struct X *q) {
  q->j = 1;
  p->i = 0;
  return q->j;
}
 
int main() {
  char *p = (char *)malloc(3 * sizeof(int));
  std::cout << foo((struct X *)(p + sizeof(int)), (struct X *)p);
}

Попробуй поизменять уровни оптимизации. Работает на GCC и Clang. Широкое применение указателей в роли ссылок привело к тому, что компилятор по умолчанию считает указатель ссылкой, но это некорректное предположение, приводящее к багам, которые невозможно отладить отладчиком — это самая писечка на тортике сишного наследия.

Даже нет нужды реализовывать это уже все сделано в С++, и либах на С которые каждый городит свои защитные будки на массивы и строки в стиле С и функции работы с такими будками

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

Я вам конкретно приводил примеры freepascal, просто не поленитесь да посмотрите как реализованы там строки

Ага, то есть, я за тебя это должен сделать. Ладно:

program test;

var
	s1, s2: String;

begin
	s1 := 'asd';
	s2 := s1;
	s1[3] := 'b';
	writeln(s1);
end.

fpc -O3 -al -Sh test.dpr

# [test.dpr]
# [6] begin
	pushq	%rbx
.Lc3:
	call	FPC_INITIALIZEUNITS
# [7] s1 := 'asd';
	movq	$_$TEST$_Ld1,%rax
	movq	%rax,%rsi
	movq	$U_$P$TEST_$$_S1,%rdi
	call	fpc_ansistr_assign
# [8] s2 := s1;
	movq	U_$P$TEST_$$_S1,%rsi
	movq	$U_$P$TEST_$$_S2,%rdi
	call	fpc_ansistr_assign
# [9] s1[3] := 'b';
	movq	$U_$P$TEST_$$_S1,%rdi
	call	fpc_ansistr_unique
	movb	$98,2(%rax)

То есть, по сути тот же машинный код.

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

Вот так новость. Ребятам из GCC надо рассказать, а то они не в курсе.

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

Но у функции должен быть один return. И тогда будет работать.(goto тоже запрещены)

Дейкстра уже давно умер, его идеи эволюционировали в иерархию Косарайю, где помимо обычных структур Бёма-Якопини (if-while) допустимы также выходы из блоков на произвольное количество уровней, что позволяет выражать те же алгоритмы короче и понятнее, чем по Бёму-Якопини.

Вообще мне понравилась эта лекция: https://www.youtube.com/watch?v=SFv8Wm2HdNM

Я тебе могу доказать, что лектор — полный мудак. Смотрим на его код realloc на 45:00 и переписанный «улучшенный» на 45:50, привожу здесь «улучшенный», как самый убогий из двух:

void * realloc(void * ptr, size_t new_size)
{
	if (!ptr)
	{
		ptr = malloc(new_size);
	}
	else if (new_size == 0)
	{
		free(ptr);
		ptr = nullptr;
	}
	else if (ptr != _Resize(ptr, new_size) || _Size(ptr) < new_size)
	{
		if (void * ptr_new = malloc(new_size))
		{
			memcpy(ptr_new, ptr, std::min(_Size(ptr), new_size));
			free(ptr);
			ptr = ptr_new;
		}
	}
	return ptr;
}

Первое, что мне пришло в голову «что будет, если я вызову someptr = NULL; realloc(someptr, 0);»? Вызов malloc(0) является implementation-defined, он не обязан возвращать корректный указатель, он не обязан возвращать нулевой указатель, но обязан возвращать значение, которое без ошибки будет прожевано free():

If ptr does not point to a memory block previously allocated with malloc, calloc or realloc, and is not a null pointer, it causes undefined behavior

Однако, этот же указатель позже имеет шансы попасть под «ptr != _Resize(ptr, new_size)», с ожидаемым выпадением в корку на отдельных платформах, поскольку проверки "!ptr" недостаточно для определения корректности указателя для realloc.

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

if (void * ptr_new = malloc(new_size))

Одна из худших черт синтаксиса Си — это возможность использовать результат присвоения как условное выражение. Здесь оно совмещено еще и с объявлением переменной. Вместо элементарного

void * ptr_new = malloc(new_size);
if (ptr_new)

Ну и самая жесть — это вот эта часть:

if (ptr != _Resize(ptr, new_size) || _Size(ptr) < new_size)

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

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

if (!(ptr == _Resize(ptr, new_size) && _Size(ptr) >= new_size))

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

if (ptr == _Resize(ptr, new_size) && _Size(ptr) >= new_size)
{
	return ptr;
}
else
{
	void *ptr_new = malloc(new_size);
	if (ptr_new)
	{
		memcpy(ptr_new, ptr, std::min(_Size(ptr), new_size));
		free(ptr);
		return ptr_new;
	}
	else
		return nullptr;

}

К слову, в своем «улучшеном» варианте он потерял возврат нуля при ошибке malloc.

Я сейчас не пытаюсь доказать, что его алгоритмом нельзя пользоваться, я не пытаюсь доказать, что он не знает языка — я лишь пытаюсь показать, что человек сидел пару часов, пыхтя над этим кодом, устраняя одни недостатки, и при этом он умудрился не заметить других элементарных проблем. Это типичный результат деятельности невротика-фантазера, который, как в школе, выполняет указания учителя в домашней работе, вроде «переделайте все сложные предложения в деепричастные обороты», при этом не обращая внимания на то, что он занимается какой-то бесполезной бредятиной и само предложение бессмысленно — его нужно выкинуть, его не нужно переписывать. И вообще, не я его писал — почему я должен его переписывать?

Такой человек без долгого перестраивания характера не сможет писать рабочий код, но это ему и не нужно — у него есть толпы таких же невротиков-фантазеров, которые точно так же не заметят очевидных проблем в коде. Короче говоря, слепой учит глухих абзуке — это суть большинства распиаренных гуру-учителей программирования.

byko3y ★★ ()
Закрыто добавление комментариев для недавно зарегистрированных пользователей (со score < 50)