【问题标题】:struct initialization fails with GCC 4GCC 4 的结构初始化失败
【发布时间】:2011-10-11 10:59:31
【问题描述】:

在我的 x86_64 Linux 机器上使用 GCC 4.5.3 初始化结构时,我遇到了一个非常奇怪的问题。

有问题的代码:

struct apr_finfo_t info = { 0 };

apr_finfo_t 是一个相当复杂的结构。我只想说它有 17 个复杂的其他成员。

struct apr_finfo_t {
    /** Allocates memory and closes lingering handles in the specified pool */
    apr_pool_t *pool;
    /** The bitmask describing valid fields of this apr_finfo_t structure 
     *  including all available 'wanted' fields and potentially more */
    apr_int32_t valid;
    /** The access permissions of the file.  Mimics Unix access rights. */
    apr_fileperms_t protection;
    /** The type of file.  One of APR_REG, APR_DIR, APR_CHR, APR_BLK, APR_PIPE, 
     * APR_LNK or APR_SOCK.  If the type is undetermined, the value is APR_NOFILE.
     * If the type cannot be determined, the value is APR_UNKFILE.
     */
    apr_filetype_e filetype;
    /** The user id that owns the file */
    apr_uid_t user;
    /** The group id that owns the file */
    apr_gid_t group;
    /** The inode of the file. */
    apr_ino_t inode;
    /** The id of the device the file is on. */
    apr_dev_t device;
    /** The number of hard links to the file. */
    apr_int32_t nlink;
    /** The size of the file */
    apr_off_t size;
    /** The storage size consumed by the file */
    apr_off_t csize;
    /** The time the file was last accessed */
    apr_time_t atime;
    /** The time the file was last modified */
    apr_time_t mtime;
    /** The time the file was created, or the inode was last changed */
    apr_time_t ctime;
    /** The pathname of the file (possibly unrooted) */
    const char *fname;
    /** The file's name (no path) in filesystem case */
    const char *name;
    /** The file's handle, if accessed (can be submitted to apr_duphandle) */
    struct apr_file_t *filehand;
};

现在,当使用 GCC 4.5.3 和 -std=c99 -pedantic -Wextra 编译这篇文章时,我看到以下警告消息:

src/switch_apr.c: In function ‘switch_file_exists’:
src/switch_apr.c:518: warning: missing initializer
src/switch_apr.c:518: warning: (near initialization for ‘info.valid’)

显然 GCC 尝试初始化第一个成员,但已经阻塞了第二个成员。 不使用 -W / -Wextra 构建时不会出现此警告。

可以手动初始化每个成员,但这听起来很奇怪和错误。

从我从 Google 搜索中收集到的信息来看,这个初始化似乎是完全合法的,并且有关于 GCC 3 的报告它在哪里工作。但 GCC 4.5 或 4.1 不适用。

希望有人可以提供帮助。 :)

最好的问候,

米海

【问题讨论】:

  • 你不是说-pedantic吗?

标签: c gcc-warning


【解决方案1】:

-Wextra 命令行选项包括 -Wmissing-field-initializers
尝试将-Wno-missing-field-initializers 添加到您的命令行。

$ 猫 7724939.c #include 结构任何{ 诠释一个; 诠释 j; 诠释 k; }; 诠释主要(无效){ 任何结构 x = {0}; 如果(x.k)返回EXIT_FAILURE; 返回0; } $ gcc --版本 gcc (Debian 4.6.1-4) 4.6.1 版权所有 (C) 2011 Free Software Foundation, Inc. 这是免费软件;查看复制条件的来源。没有 保修单;甚至不考虑适销性或特定用途的适用性。 $ gcc -std=c99 -pedantic 7724939.c $ gcc -std=c99 -pedantic -Wall -Wextra 7724939.c 7724939.c:在函数“main”中: 7724939.c:10:10:警告:缺少初始化程序 [-Wmissing-field-initializers] 7724939.c:10:10:警告:(接近初始化“x.j”)[-Wmissing-field-initializers] $ gcc -std=c99 -pedantic -Wall -Wextra -Wno-missing-field-initializers 7724939.c $

请注意,C 标准不要求该警告。只是你的编译器试图(太)有帮助。

【讨论】:

  • 是的,没错(我也暗示过),但由于 GCC 使用 -Werror 实际上 is 发出一些警告消息,我确实担心所有其他字段不要初始化。我可以很好地禁用警告,但可能只会“掩盖”问题。
  • 使用{ 0 },所有字段都被初始化为0的正确类型。请参阅C99 Standard 中的第 6.7.8/19 节:“所有未显式初始化的子对象都应隐式初始化,与具有静态存储持续时间的对象相同。”
  • 那么为什么 GCC 声称他们不是……哦,等等,它没有声称。它声称您没有为所有其他成员指定初始化程序(即手动),但它仍然应该从第一个成员继承。这次我做对了吗?
  • 它不会从第一个继承...所有未显式初始化的字段都被初始化为0。我喜欢将{0} 称为通用零初始化器:它适用于所有事物——int k = {0}; void *foo = {0}; char buffer[2000] = {0}; struct complicated stuff[42] = {0}; ...
  • 如果列表中不使用0,则只有对应的字段获取该值;所有其他人得到0。在struct twoints { int a; int b; }; struct twoints x = {4}; 之后,您将拥有x.a == 4;x.b == 0;
【解决方案2】:

如果你使用 C++,最好包含一个初始化的构造函数,这样初始化只需要写在构造函数中而不是到处。

【讨论】:

  • 当然,但这显然不是我的代码,我不会用 C++ 重写 APR。 ;)
猜你喜欢
  • 1970-01-01
  • 2012-03-25
  • 1970-01-01
  • 2016-05-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多