Чем отличается структура в C99 от ANSI-C?

Этот код кажется неправильным в ANSI-C, но хорошо в C99:

struct a { int x; int y; } z;

Каковы различия о структуре в C99 и ANSI-C?

Редактировать: я забыл "а", мой плохой. Этот код компилируется нормально с gcc в режиме C99, но это ошибка синтаксического анализа шины, которая, как известно, не поддерживает все расширения C99.

Edit2: здесь вывод шины

Splint 3.1.2 --- 19 Dec 2007

build/ecos_install/include/cyg/fileio/fileio.h:151:5:
Parse Error. Attempting to continue.
build/ecos_install/include/cyg/fileio/fileio.h:151:25:
Cannot recover from parse error.
*** Cannot continue.

Edit3: это файл eCos fileio.h (последняя строка этого фрагмента - строка 152):

typedef CYG_ADDRWORD cyg_dir;

//=============================================================================
// Filesystem table entry

typedef int     cyg_fsop_mount    ( cyg_fstab_entry *fste, cyg_mtab_entry *mte );
typedef int     cyg_fsop_umount   ( cyg_mtab_entry *mte );
typedef int     cyg_fsop_open     ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
                                    int mode,  cyg_file *fte );
typedef int     cyg_fsop_unlink   ( cyg_mtab_entry *mte, cyg_dir dir, const char *name );
typedef int     cyg_fsop_mkdir    ( cyg_mtab_entry *mte, cyg_dir dir, const char *name );
typedef int     cyg_fsop_rmdir    ( cyg_mtab_entry *mte, cyg_dir dir, const char *name );
typedef int     cyg_fsop_rename   ( cyg_mtab_entry *mte, cyg_dir dir1, const char *name1,
                                    cyg_dir dir2, const char *name2 );
typedef int     cyg_fsop_link     ( cyg_mtab_entry *mte, cyg_dir dir1, const char *name1,
                                    cyg_dir dir2, const char *name2, int type );
typedef int     cyg_fsop_opendir  ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
                                    cyg_file *fte );
typedef int     cyg_fsop_chdir    ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
                                    cyg_dir *dir_out );
typedef int     cyg_fsop_stat     ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
                                    struct stat *buf);
typedef int     cyg_fsop_getinfo  ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
                                    int key, void *buf, int len );
typedef int     cyg_fsop_setinfo  ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
                                    int key, void *buf, int len );


struct cyg_fstab_entry
{
    const char          *name;          // filesystem name
    CYG_ADDRWORD        data;           // private data value
    cyg_uint32          syncmode;       // synchronization mode

    cyg_fsop_mount      *mount;
    cyg_fsop_umount     *umount;
    cyg_fsop_open       *open;
    cyg_fsop_unlink     *unlink;
    cyg_fsop_mkdir      *mkdir;
    cyg_fsop_rmdir      *rmdir;
    cyg_fsop_rename     *rename;
    cyg_fsop_link       *link;
    cyg_fsop_opendir    *opendir;
    cyg_fsop_chdir      *chdir;
    cyg_fsop_stat       *stat;
    cyg_fsop_getinfo    *getinfo;
    cyg_fsop_setinfo    *setinfo;
} CYG_HAL_TABLE_TYPE;

4 ответа

struct { int x; int y; } z;

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

ofaurax, какое сообщение об ошибке вы можете сделать вывод, что оно не работает?

(Pedantic nit: "ANSI C" означает версию C, стандартизированную ANSI, Американским национальным институтом стандартов. Версия стандарта ANSI C 1989 года была принята Международной организацией по стандартизации ISO. В 1999 году ISO выпустила новую версию C стандартом, который ANSI затем принял обратно.)

Редактировать:

struct a { int x; int y; } z;

Это определяет тип структуры, называемый "struct a", состоящий из двух целых и переменной z этого типа. Это все еще хорошо сформировано даже в версии C 1978 года ("K&R"). Я не знаю, что такое разделение, но точные сообщения об ошибках все равно, вероятно, помогут нам выяснить, в чем проблема.

Не слишком уверен, но в "старых" компиляторах я помню, что писал это как

typedef struct _Z {int x; int y;} z; or just typedef struct {int x; int y;} z;

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

Если вы доверяете компилятору, чтобы сказать вам разницу, какой компилятор / версию вы используете?

Файл, содержащий только этот код, анализируется Splint 3.1.2.

Можете ли вы предоставить простой, полный пример, который демонстрирует поведение, которое вы описываете?

Немного поэкспериментируя, мы видим, что splint, похоже, не поддерживает смешанный код и объявления, и это меня оттолкнет. Так что код, который вы выложили сам по себе, в порядке, но это даст ошибку разбора:

void foo () {
   int x = 1;
   ++x;
   struct a { int x; int y; } z;
}

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

$ diff original/src/cgrammar.y src/cgrammar.y
1711a1712
>  | initializer
Другие вопросы по тегам