Как структурировать вашу c программу? - PullRequest
8 голосов
/ 13 октября 2009

Я работаю / пишу на C # / Java уже несколько лет, поэтому основы и т. Д. Не доставляют мне больших трудностей. Но я никогда не делал ничего большего, чем небольшие программы обучения на командной строке в c.

Сейчас я пытаюсь сделать эмулятор мобильного телефона для Linux, и я понятия не имею, как структурировать мой код, когда он не объектно-ориентирован. У меня есть 3 большие книги, которые подробно описывают c, но ни одна из них не описывает, как писать код для удобства сопровождения в большем проекте.

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

Ответы [ 7 ]

7 голосов
/ 13 октября 2009

Некоторые мысли (и этот вопрос должен быть вики сообщества)

  • Даже если это не полноценное объектно-ориентированное программирование, старайтесь придерживаться методов сокрытия информации. Позвольте вашим функциям возвращать указатели или дескрипторы непрозрачных структур (хороший (ранний) пример - дескриптор файла unix). Используйте static функции, где вы иначе использовали бы private методы.
  • Старайтесь хранить связанные функции, содержащиеся в одном файле. Это облегчит использование вышеупомянутого ключевого слова static, а также даст вам хорошее представление о том, когда пришло время разделить некоторые функции в отдельный файл. Для программиста на Java это не должно быть слишком странной практикой.
  • Применяется стандартная практика комментирования. Используйте что-то вроде Doxygen , если вы ищете что-то похожее на комментарии javadoc / C # XML.
  • Если вы действительно какое-то время не делали ничего серьезного в C, вам придется столкнуться с практикой поддержания чистоты и разумности управления памятью, даже если это не сложно само по себе, будет больно намного больше, чем установление практики для ремонтопригодности. Просто предупреждение.
2 голосов
/ 13 октября 2009

Я бы порекомендовал разбить ваш проект на более мелкие компоненты и поместить каждый компонент в свои собственные файлы .c и .h. Вы помещаете код в файл .c, а структуры и прототипы - в файл .h.

Делая это, вы можете программировать объектно-ориентированный язык на C, если сохраняете свои функции повторными: скажем, пара функций выполняет функцию FOO, а затем вместо глобальных переменных в foo.c объявляется структура с именем FOO в foo.h , в которой функции принимают указатель на структуру FOO в качестве первого параметра.

Если функция fred() используется только где-то в foo.c , отметьте ее static и не помещайте прототип в foo.h

Кроме того, выполните поиск Google codesearch для проектов C, чтобы увидеть, как это делается.

2 голосов
/ 13 октября 2009

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

Часто с C вы все еще можете думать об объектах. Но вместо классов с методами они являются структурами и функциями, которые работают со структурой.

1 голос
/ 13 октября 2009

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

Подобные методы все еще используются сегодня - GIMP построен на GTK + , который включает в себя библиотеку GObject для объектно-ориентированного кодирования на C. Это может быть не лучшим способом, и не может быть "идиоматическим" C, но это может помочь вам.

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

GTK + еще раз имеет GLib , которая является универсальной библиотекой с множеством функций, которые люди реализовали и реализовали в C. Apache имеет свою собственную, Apache Portable Runtime , что делает что-то очень похожее (но с различными видами функций). Есть также несколько строковых библиотек, которые, вероятно, избавят вас от головной боли, и несколько библиотек специального назначения (Readline для интерактивных подсказок, Ncurses для текстовых интерфейсов, таких как vi и т. Д.), Которые полезны, но не могут играть огромную роль в ваше конкретное заявление.

Лучший выбор в некоторой степени зависит от того, что вы пишете. Если вы пишете ядро ​​операционной системы, драйвер устройства или какое-либо приложение для встроенных систем, не обращайте внимания на все вышеперечисленные советы. Если вы хотите реализовать язык программирования, изучите flex и bison, чтобы начать работу с грамматиками в нескольких небольших тестовых проектах, но я рекомендую использовать собственный анализатор и лексер для серьезного проект (если не по какой-либо другой причине, кроме улучшенной отчетности об ошибках).

0 голосов
/ 14 октября 2009

Несколько предложений ...

& бык; Максимально используйте модификатор static; это (в основном) эквивалент private в языках OO.

& бык; Старайтесь не использовать слишком много глобальных переменных, особенно если ваша программа использует несколько потоков.

& бык; Сгруппируйте связанную информацию в structs; это ваши объекты в C.

& бык; В C нет обработки исключений, поэтому проверьте возвращаемые значения всех системных функций, которые вы вызываете.

0 голосов
/ 13 октября 2009

ОО - это просто синтаксический сахар. Оригинальные компиляторы C ++ скомпилированы для C. Вот базовый пример примерно одного и того же класса в Java и в C:

Point.java
import java.lang.Math;

public class Point
{
    private int x, y;

    public Point(int x, int y)
    {
        this.x = x;
        this.y = y;
    }

    public int getDistance(Point p)
    {
        return Math.sqrt((p.x - this.x) * (p.x - this.x) + (p.y - this.y) * (p.y - this.y));
    }
}

Point.h
typedef struct __Point Point;
typedef struct __Point
{
    int x, y;
    int (*getDistance)(Point*,Point*);
} Point;

Point* new_Point(int, int);
void delete_Point(Point*);
int getDistance(Point*, Point*);

Point.c
#include <math.h>
#include "Point.h"

Point* new_Point(int x, int y)
{
   Point* this = malloc(sizeof(Point));
   this->x = x;
   this->y = y;
   this->getDistance = getDistance;
}

void delete_Point(Point* this)
{
    free(this);
}

int getDistance(Point* this, Point* p)
{
    return sqrt((p->x - this->x) * (p->x - this->x) + (p->y - this->y) * (p->y - this->y));
}
0 голосов
/ 13 октября 2009
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...