Подтвердить что ты не робот

Обучение C, когда вы уже знаете С++?

Я думаю, что у меня есть передовое знание С++, и я бы хотел узнать C.

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

В частности:

  • Существуют ли широко используемые библиотеки общего назначения, о которых должен знать каждый программист C (например, boost для С++)?
  • Каковы наиболее важные C-идиомы (например, RAII для С++)?
  • Должен ли я изучать C99 и использовать его или придерживаться C89?
  • Любые ловушки/ловушки для разработчика С++?
  • Что-нибудь еще полезно знать?
4b9b3361

Ответ 1

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

Библиотека:

  • Я положил это первым, потому что это, на мой взгляд, это самая большая разница на практике. Стандартная библиотека C очень (!) Разрежена. Он предлагает минимум услуг. Для всего остального вы должны сворачивать свои собственные или находить библиотеку для использования (и многие люди). У вас есть файловый ввод-вывод и некоторые очень простые строковые функции и математика. Для всего остального вам нужно сворачивать самостоятельно или найти библиотеку для использования. Я нахожу, что я сильно пропускаю расширенные контейнеры (особенно карты) при переходе с С++ на C, но есть много других.

Идиомы:

  • Оба языка имеют ручное управление памятью (ресурсами), но С++ дает вам некоторые инструменты, чтобы скрыть необходимость. В C вы будете чаще отслеживать ресурсы вручную, и вам придется привыкнуть к этому. Конкретными примерами являются массивы и строки (С++ vector и string сэкономит вам много работы), умные указатели (вы не можете действительно делать "умные указатели" как таковые в C. Вы можете делать подсчет ссылок, но у вас есть чтобы вверх и вниз подсчитывать ссылки, которые очень подвержены ошибкам - причина, по которой умные указатели были добавлены в С++, в первую очередь), и отсутствие RAII в целом, которое вы заметите повсюду, если вы привыкли к современному стилю С++.
    • Вы должны быть откровенно о строительстве и разрушении. Вы можете спорить о достоинствах недостатков этого, но в результате появляется намного более явный код.
  • Обработка ошибок. Исключения С++ могут быть сложными, чтобы получить право, поэтому не все их используют, но если вы их используете, вы обнаружите, что вам нужно уделять много внимания тому, как вы делаете уведомление об ошибке. Необходимость проверять возвращаемые значения на всех важных вызовах (некоторые из них будут аргументировать все вызовы) требует много дисциплины, и много кода C там не делает этого.
  • Строки (и массивы вообще) не имеют размеров. Вы должны передать много дополнительных параметров в C, чтобы справиться с этим.
  • Без пространств имен вы должны тщательно управлять своим глобальным пространством имен.
    • Там нет явной привязки функций к типам, как есть с class в С++. Вы должны поддерживать соглашение о префиксации всего, что вы хотите связать с типом.
  • Вы увидите намного больше макросов. Макросы используются в C во многих местах, где С++ имеет языковые возможности, чтобы сделать то же самое, особенно символические константы (C имеет enum, но в большинстве старых кода используется #define), а для generics (где С++ использует шаблоны).

Совет:

  • Рассмотрите возможность поиска расширенной библиотеки для общего использования. Взгляните на GLib или APR.
    • Даже если вы не хотите, чтобы полная библиотека рассматривала поиск карты/словаря/хеш-таблицы для общего использования. Также подумайте о наборе типа "строка" голых костей, который содержит размер.
  • Привыкнуть к установке префиксов модулей или классов для всех общедоступных имен. Это немного утомительно, но это сэкономит вам много головных болей.
  • Внимательно используйте форвардную декларацию, чтобы сделать типы непрозрачными. Где на С++ у вас могут быть личные данные в заголовке и полагаться на private на предотвращение доступа, на C вы хотите как можно больше вставлять детали реализации в исходные файлы. (На самом деле, вы на самом деле хотите сделать это на С++, но C упрощает его, поэтому все больше людей делают это.)

    С++ показывает реализацию в заголовке, даже если он технически скрывает его от доступа вне класса.

    // C.hh
    class C
    {
        public:
           void   method1();
           int    method2();
    
       private:
           int    value1;
           char * value2;
    };
    

    C толкает определение класса в исходный файл. Заголовок - это все форвардные объявления.

    // C.h
    typedef struct C C;           // forward declaration
    
    void c_method1(C *);
    int  c_method2(C *);
    
    // C.c
    struct C
    {
        int    value1;
        char * value2;
    };   
    

Ответ 2

Glib является хорошей отправной точкой для современного C и позволяет вам привыкнуть к таким концепциям, как непрозрачные типы и ориентация полуобъектов, которые общий стилистически в современном C. На другом конце спектра стандартные API POSIX являются своего рода "классическими".

Самый большой разрыв при переходе с С++ на C - не синтаксис, это идиома, и там, как и на С++, существуют разные школы программирования. Вы будете писать довольно разные C, если вы используете драйвер устройства, например, XML-парсер.

Ответ 3

Q5. Что-нибудь еще полезно знать?

Купите копию K & R2 и прочитайте ее. По стоимости на каждую страницу это, вероятно, будет самая дорогая книга по вычислениям, которую вы когда-либо покупали своими деньгами, но это даст вам глубокую оценку C и мыслительные процессы, которые вошли в нее. Выполнение упражнений также оттачивает ваши навыки и помогает вам привыкнуть к тому, что доступно на языке, в отличие от С++.

Ответ 4

Отвечая на ваши вопросы в порядке:

  1. К сожалению, нет ничего подобного Boost для C.
  2. Ничего, что действительно по порядку RAII.
  3. Единственный компилятор, который пытается реализовать C99, - это Комо.
  4. Многие из них повсюду, я боюсь.
  5. Совсем немного. C принимает совсем другое мышление, чем C.

Некоторые из них могут казаться довольно краткими, но такова жизнь. Для C есть несколько хороших библиотек, но ни одно место вроде Boost, которое они собирали вместе, или не имеет относительно однородного интерфейса, такого как Boost, для С++.

Есть много идиом, но многие из них относятся к тому, как вы редактируете свой код, например, как имитируете RAII, написав fopen() и соответствующий fclose() в быстрой последовательности, и только после этого введя код в между обработкой данных.

Ловушки/ловушки, которые ждут каждого угла, в основном связаны с отсутствием динамических структур данных, таких как строка и вектор, поэтому вам часто приходится писать такие вещи самостоятельно. Без перегрузки оператора, конструкторов и т.д. Значительно сложнее сделать их действительно общей целью. Многие библиотеки имеют их, но в итоге вы все равно катитесь, потому что:

  1. библиотека не делает то, что вы хотите, или
  2. с помощью библиотеки работает больше, чем стоит.

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

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

Изменить (поскольку люди задавали вопросы о поддержке C99): Хотя мое утверждение об отсутствии поддержки C99 может показаться суровым, факт в том, что это правда.

MS VС++: поддерживает C95 и имеет пару функций C99 (например, разделители комментариев в стиле С++), главным образом потому, что C99 стандартизовал то, что они ранее имели в качестве расширения.

Gnu: Согласно странице C99 Features Status, последняя итерация gcc (4.4) имеет некоторые функции C99, но некоторые (включая VLA) характеризуются как "сломанные", а другие - как "отсутствующие". Некоторые из недостающих "функций" - это целые области, а не отдельные функции.

PCC: сайт PCC утверждает соответствие C99 только как цель на будущее, а не как настоящую реальность.

Embarcadero Technologies (nee Borland), похоже, ничего не говорит о совместимости с C99 - от взглядов вещей, последний раз, когда они работали над компилятором C, вполне возможно, было еще до того, как C99 был выпущен.

Microsoft открыто заявляет, что у них нет текущих планов поддержки C99, и они не собираются даже рассматривать его до тех пор, пока VS 2010 не будет выпущенный. Хотя я не могу найти никаких публичных заявлений об этом, Embarcadero появляется примерно одинаково: никаких намеков на текущий план и даже не на то, что они собираются рассмотреть возможность работы с ним в ближайшее время.

В то время как у gcc и pcc оба имеют планы, они в настоящее время только таковы: планы. Они оба открыто признают, что в настоящее время они на самом деле не очень близки к соответствию с C99.

Ответ 5

Здесь краткая ссылка некоторых основных вещей, которые вы хотите знать.

Ответ 6

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

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

Но не слушайте меня. Я был слишком ленив и глуп, чтобы изучить С++:)

Ответ 7

Что-нибудь еще полезно знать?

C99 не является подмножеством С++ любой версии, а отдельным языком.

Ответ 8

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

Ответ 9

Почти самый большой удар, который у меня был, когда я вернулся к C, заключался в том, что переменные определяются на уровне функции - то есть вы не можете изменять переменные области внутри блока (оператор if или цикл for) внутри функции.

Ответ 10

Поскольку С++ является почти надмножеством C89, вы должны знать почти все C89. Вероятно, вы хотите сосредоточиться на различиях между C89 и C99.