LCC: Инициализация структур, содержащих структуры? - PullRequest
1 голос
/ 01 сентября 2011

Следующий фрагмент кода прекрасно компилируется в Mac OS X с gcc, но не компилируется в Windows с lcc-win32:

typedef struct Foo Foo;
typedef struct Bar Bar;

struct Bar { int age; int height; };
struct Foo { Bar barOne; Bar barTwo; };

// Elsewhere, in some function:

Bar barOne = { 2, 4 };
Bar barTwo = { 6, 8 };
Foo instance = { barOne, barTwo };

и выдает эту ошибку:

найдено 'struct Bar' ожидается 'int'

Я могу «преодолеть» это, инициализируя структуру следующим образом:

Foo instance = { barOne.age, barOne.height, barTwo.age, barTwo.height };

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

Мне интересно, является ли LCC "более строгим" (придерживающимся какого-то стандарта) или "более тупым" (компилятор слишком туп, чтобы справиться с этой ситуацией).

Спасибо.

Также, пожалуйста, смотрите мой другой вопрос LCC-Win32: LCC: предварительная декларация Typedef'd Enum Failing?

Ответы [ 2 ]

3 голосов
/ 01 сентября 2011

Как написано:

typedef struct Foo Foo;
typedef struct Bar Bar;

struct Foo { Bar barOne; Bar barTwo; };
struct Bar { int age, int height };

// Elsewhere, in some function:

Bar barOne = { 2, 4 };
Bar barTwo = { 6, 8 };
Foo instance = { barOne, barTwo };

код не должен компилироваться везде (и, в частности, происходит сбой в MacOS X 10.7.1 с GCC 4.6.0) с этими ошибками (плюс некоторые другие):

xx.c:4: error: field ‘barOne’ has incomplete type
xx.c:4: error: field ‘barTwo’ has incomplete type

Это потому, что вы пытаетесь использовать Bar до его определения. Поменяйте порядок определений структуры и исправьте синтаксические ошибки в Bar (запятая должна быть точкой с запятой; пропущена точка с запятой), а затем (наконец) она скомпилируется в MacOS X.

Что стандарт говорит об использовании структур в качестве инициализаторов?

§6.7.8 Инициализация

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

Рассмотрим контекст функции (этот код компилируется нормально с GCC, установленным суетой):

typedef struct Foo Foo;
typedef struct Bar Bar;

struct Bar { int age; int height; };
struct Foo { Bar barOne; Bar barTwo; };

void somefunction(void)
{
    Bar barOne = { 2, 4 };
    Bar barTwo = { 6, 8 };
    Foo instance = { barOne, barTwo };
}

Внешне мне кажется, что barOne и barTwo не являются отдельными выражениями. Тем не менее, стандарт гласит:

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

Если агрегаты должны быть заключены в фигурные скобки, то написать это будет работать:

Foo instance = { { barOne }, { barTwo } };

GCC, однако, категорически отвергает эту конструкцию.

i686-apple-darwin11-llvm-gcc-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)

/usr/bin/gcc -g -std=c99 -Wall -Wextra -Wmissing-prototypes -c xx.c
xx.c:8: warning: no previous prototype for ‘somefunction’
xx.c: In function ‘somefunction’:
xx.c:11: error: incompatible types in initialization
xx.c:11: warning: missing initializer
xx.c:11: warning: (near initialization for ‘instance.barOne.age’)
xx.c:11: error: incompatible types in initialization
xx.c:11: warning: missing initializer
xx.c:11: warning: (near initialization for ‘instance.barTwo.age’)
xx.c:11: warning: missing initializer
xx.c:11: warning: (near initialization for ‘instance.barOne’)
xx.c:11: warning: unused variable ‘instance’

В целом, я склонен доверять решению GCC и указывать пальцем на то, что LCC не рассматривает дело должным образом. Диспуты, которые потребуют полного разбора §6.7.8 стандарта C, и я не предоставил весь материал (он идет до ¶23, прежде чем начинать на примерах).

1 голос
/ 01 сентября 2011

Ну, это не называется Little C Compiler иногда даром.Он может справиться с большинством вещей, но, чтобы сэкономить пространство и время, он, как правило, будет более строгим в этих случаях.Реализация чего-то, что выглядит просто, обычно не в компиляторе.Либо это, либо LCC просто никогда не обновлялись, чтобы справиться с этими ситуациями.Есть ли конкретная причина для использования LCC вместо Borland, MSVC ++, Cygin / MingW32 gcc?

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