C структуры не определяют типы? - PullRequest
3 голосов
/ 15 ноября 2009

Я только начал изучать C с профессиональным опытом Java и некоторыми (если не слишком много) знаниями C ++, и я был удивлен, что это не работает в C:

struct Point {
    int x;
    int y;
};

Point p;

p.x = 0;
p.y = 0;

Кажется, я должен объявить p, используя struct Point в качестве типа или typedef. Этот код работает в C99? Или это "C ++ вещь"?

Ответы [ 10 ]

7 голосов
/ 15 ноября 2009

Насколько я знаю, он также не должен работать без typedef в C99 (так как это просто способ работы C), но он работает в C ++, так как struct в C ++ - это просто class со всеми участниками по умолчанию.

5 голосов
/ 15 ноября 2009

Нет, структура не определяет новый тип. Что вам нужно, это:

typedef struct {
   int x; int y;
} Point;

Теперь Point - это новый тип, который вы можете использовать:

Point p;
p.x = 0; p.y = 0;
4 голосов
/ 16 ноября 2009

В C нет путаницы между

struct Point {
    int x;
    int y;
};

и

union Point {
    int x;
    int y;
};

это два разных типа, которые называются struct Point и union Point соответственно.

В стандартном разделе 6.7.2.1 C99 указано:

6 Спецификаторы структуры и объединения имеют такая же форма. Ключевые слова struct и union означает, что тип указано, соответственно, тип конструкции или тип объединения.

7 наличие списка объявляемых структур в спецификаторе структуры или объединения объявляет новый тип, в пределах переводческая единица.

Так что это наиболее однозначно объявляет тип. Синтаксис для имен типов в C приведен в разделах 6.7.6 и включает в себя спецификатор-список-спецификатор из 6.7.2, который принимает форму struct-or-union identifier.

Этот код работает в C99? Или это "C ++ вещь"?

Нет, C99 не принимает решение о продвижении типов структуры по типам enum и типам объединения с одинаковыми именами. Это «вещь C ++», так как структура и классы в C ++ в основном одно и то же, а классы важны для C ++.

4 голосов
/ 15 ноября 2009

struct Point - это тип , как и union Foo. Вы можете использовать typedef, чтобы присвоить ему другое имя - typedef struct Point Point;.

2 голосов
/ 16 ноября 2009

Итак ...

Point           a tag
struct Point    a type

typedef struct {
    . . .
} Point_t;

Point_t         a type

Я часто вижу почему? написано между строк. В конце концов, кажется вполне разумным просто сказать Point x;, так почему вы не можете?

Как оказалось, ранние реализации C установили отдельное пространство имен для тегов и других идентификаторов. На самом деле 4 пространства имен 1 . После того, как язык был определен таким образом, стало невозможным использование тега struct в качестве типа, потому что тогда весь существующий код с конфликтами имен между обычными идентификаторами и тегами внезапно ошибиться.


1. 4 именных пространств :
- имена меток (устраняются неоднозначно по синтаксису объявления и использования меток);
- теги структур, объединений и перечислений (устраняющих неоднозначность, следуя любому) ключевых слов struct, union или enum);
- члены структур или союзов; каждая структура или союз имеет отдельное имя пространство для его членов (неоднозначно по типу выражения, используемого для доступа к член через. или -> оператор);
- все остальные идентификаторы, называемые обычными идентификаторами (объявленные в обычных деклараторах или как константы перечисления)

1 голос
/ 15 ноября 2009

В C структуры могут иметь два вида имен: имя тега и имя типа. Имя тега можно использовать только в том случае, если перед ним стоит структура, например:

struct mytag { int a; }
struct mytag mystruct;

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

typedef struct mytag { int a; } mytype;
mytype mystruct; // No struct required
1 голос
/ 15 ноября 2009

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

struct Point p;
p.x = 0;
p.y = 0;

Если вы хотите использовать структуру в качестве типа, вы должны ввести ее. Это работает как на C, так и на C ++:

typedef struct _point {
    int x;
    int y;
} Point;

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

1 голос
/ 15 ноября 2009

Это не работает в C99, это вещь C ++. Вы должны либо сказать struct Point, либо использовать typedef в C.

0 голосов
/ 15 ноября 2009

Сначала нужно сделать Point типом:

typedef struct Point {
    int x;
    int y;
} Point;

Это позволяет вам использовать Point как тип или struct Point

т.е:

Point *p;

sizeof(struct Point);

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

typedef struct _point {
       ...
} Point;

Вы столкнетесь с обоими. Последний пример говорит мне, что я не должен использовать struct _point, он не предназначен для показа, за исключением типа Point.

0 голосов
/ 15 ноября 2009

Так работает С. В C вы должны сказать:

typedef struct Point {
    int x;
    int y;
} Point;

И тогда у вас будет тип с именем Point, который делает то, что вы хотите.

В C ++ достаточно определить его так, как вы это сделали.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...