代码之家  ›  专栏  ›  技术社区  ›  ofaurax

c99中的struct与ansi-c有什么不同?

  •  1
  • ofaurax  · 技术社区  · 17 年前

    此代码在ANSI-C中似乎不正确,但在C99中正常:

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

    c99和ansi-c中的struct有什么不同?

    编辑:我忘了“A”,我的错。这段代码在c99模式下可以与gcc一起编译,但在splint上是一个解析错误,众所周知,splint不支持所有的c99扩展。

    编辑2:这是夹板的输出:

    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 回复  |  直到 15 年前
        1
  •  4
  •   user25148    17 年前
    struct { int x; int y; } z;
    

    这段代码是有效的C,具有相同的语义,从1978年以后的每一个C版本开始,可能更早。它定义了一个名为z的变量,该变量的类型是一个无名称的结构类型,它由两个int组成。

    奥法克斯,你得到了什么错误信息来断定它不起作用?

    (学究式的nit:“ansi c”是指美国国家标准协会ansi标准化的c版本。1989年版的ANSI C标准被国际标准组织ISO采用。1999年,国际标准化组织(ISO)制定了新版本的C标准,随后美国国家标准化组织(ANSI)又采用了该标准。)

    编辑:

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

    它定义了一个结构类型,称为“struct a”,由两个int和一个该类型的变量z组成。即使在1978年的C(“K&R”)版本中,这一点仍然很完善。我不知道split是什么,但确切的错误消息仍然可能帮助我们找出问题所在。

        2
  •  1
  •   Fredrik Jansson    17 年前

    不太确定,但在“旧的”编译器中,我记得必须写为

    typedef struct _Z {int x; int y;} z; or just typedef struct {int x; int y;} z;
    
        3
  •  1
  •   Tim Post Samir J M Araujo    17 年前

    您能显示实际的编译器警告、编译器标志和相关的代码行吗?你的例子绝对没有错。或者,也许是一个链接,指向你得出结论的文件?

    如果您信任编译器来告诉您区别,那么您使用的编译器/版本是什么?

        4
  •  1
  •   Pete Kirkham    17 年前

    一个只包含该代码的文件可以通过 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