Почему программы на C продолжают говорить «struct» каждый раз, когда ссылаются на одну из них? - PullRequest
2 голосов
/ 05 ноября 2011

Хотя я редко пишу код на C, я часто вижу его (в основном из-за того, что книги в моей области используют его как эталонный язык для примеров алгоритмов), и какое-то время меня беспокоило способ объявления переменных / параметров , Лучшим примером был бы этот список с примером твиста, о конкретной реализации Linked List, используемой в ядре Linux (извините, у меня изначально была ссылка на пост в блоге, но, очевидно, пост в блоге был удален, я скопировал код из кеш браузера).

struct blog {
  ...
  struct ls posts;
};

struct post {
  ...
  struct ls blog_posts;
};

void delete_blog(struct blog *blog) {
  ...
  struct post *p;
  ls_for_each(&blog->posts, p, blog_posts) {
    free(p);
  }
  free(blog);
}

Что меня беспокоит, так это то, что они повторяют ключевое слово struct везде. Я имею в виду такие вещи, как ls, blog, post , которые объявляются как структуры, так какой смысл говорить, что это структура каждый раз, когда вы объявляете переменную или параметр функции этого типа? Что это говорит компилятору, что он не может сделать вывод из того факта, что объект, который вы создали, был определен как структура?

Ответы [ 5 ]

6 голосов
/ 05 ноября 2011

struct теги находятся в другом пространстве имен, чем обычные идентификаторы.Таким образом, ключевое слово struct необходимо указать это.Известный пример в POSIX, где у вас есть struct stat и функция stat.

5 голосов
/ 05 ноября 2011

Ну, это потому, что если нет typedef, это единственный способ обратиться к структуре.

В C, если у вас есть:

struct thing {
  // stuff here
};

и вы хотите иметь переменную этого типа, вам нужно либо:

  • используйте struct thing в качестве спецификатора типа
  • создайте typedef наподобие typedef struct thing thing_t; и используйте thing_t в качестве спецификатора типа.

(C ++ отличается в этом отношении.)

3 голосов
/ 05 ноября 2011

Это просто синтаксис ...

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

«Typedef» был добавлен в язык, чтобы разрешить создание более коротких имен, которые не включали структуру, однако используется полный синтаксис структуры - и, в частности, используется в историческом контексте, где исходное определение структуры системы определяется как "struct" без соответствующей краткой формы typedef.

В качестве сравнения C ++, который является гораздо более поздним языком, позволяет ссылаться на класс / структуру только по имени класса / структуры независимо от того, был ли он определен с помощью typedef.

Итак, когда возникают вопросы, ответ таков: просто так, потому что это ...

EDIT : просто глядя на ваш пример кода, есть один примечательный случай, когда struct добавляет что-то к поведению компилятора - в большинстве случаев тип должен быть определен до того, как его можно будет использовать в другом объявление - за исключением случаев, когда вы ссылаетесь на struct sometype* (то есть указатель на структуру), и в этом случае компилятор с радостью определит sometype после использования.

так

struct post {
   struct post *nextpost;
   struct post *prevpost;
   ...
};

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

1 голос
/ 05 ноября 2011

Многие современные библиотеки C систематически typedef имеют свои struct и используют некоторые соглашения об именах.Например, gtk/gtkalignment.h имеет:

typedef struct _GtkAlignment              GtkAlignment;
typedef struct _GtkAlignmentPrivate       GtkAlignmentPrivate;
typedef struct _GtkAlignmentClass         GtkAlignmentClass;

Моя собственная привычка - указывать foo_st struct и foo_t тип, поэтому я часто кодирую

typedef struct foo_st foo_t;

И я бы использовал union foo_un, если это где union.

1 голос
/ 05 ноября 2011

struct является частью объявления типа.

Если функция принимает аргумент (/ параметр), тогда тип этого аргумента должен быть объявлен.Как вы могли бы объявить, что этот аргумент является структурой, если вы не можете использовать слово struct?

...