Чем отличается структура в C99 от ANSI-C? - PullRequest
1 голос
/ 27 января 2009

Этот код кажется неправильным в 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 ]

4 голосов
/ 27 января 2009
struct { int x; int y; } z;

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

ofaurax, какое сообщение об ошибке вы считаете, что оно не работает?

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

Edit:

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

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

1 голос
/ 27 января 2009

Файл, содержащий только этот код, анализируется 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
1 голос
/ 27 января 2009

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

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

1 голос
/ 27 января 2009

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

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