gcc 可能的错误?带有点符号的结构中缺少初始值设定项

gcc possible bug? missing initializer in struct with dot notation

我正在使用这些 gcc 标志编译我的程序:-std=c11 -Wall -Wextra -pedantic.

我正在尝试使用带有字段标签的初始化程序来初始化结构,而不是记住每个字段的正确顺序。但是我收到一些我不明白的警告。在另一个问题中,有人声称这可能是一个 gcc 错误......我不知道。

这是我的代码。我尝试使用冒号 : 表示法,但收到过时的初始化程序警告,因此我切换到点 . 表示法。

这真的只是一个错误,还是我这里做错了什么?我可以抑制那个警告,但我认为它一开始就不应该出现。我仔细检查了我的代码,它应该是正确的,对吧?编译器应该很高兴,不会发出警告。

如果我弄错了或者忘记了什么,请告诉我

编辑:我尝试做的"thing"真的是C11标准吗? Can I 'extend' a struct in C?

编辑 2:已解决。请参阅下面我的回答

student/student.h:

#ifndef STUDENT_H
#define STUDENT_H

#define IDSIZE 7 + 1 // 7x char + '[=10=]' terminator

typedef enum gender {
    MALE = 'M',
    FEMALE = 'F',
    OTHER = 'O'
} gender_t;

typedef struct date {
    short day;
    short month;
    int year;
} date_t;

typedef struct person {
    char *firstname;
    char *lastname;
    date_t birthdate;
    gender_t gender;
} person_t;

typedef struct student {
    char id[IDSIZE];

    struct person; // "extends" from struct person
} student_t;

#endif

es3.c:

/**
 * Trying to refactor the student crazy shit stuff of a previous exercise.
 */

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

#include "student/student.h"

void die(const char * format, ...);

int main(int argc, char **argv) {
    if (argc < 2)
        die("Usage: %s inputfile.txt\n", argv[0]);

    puts("Ok");

    student_t student = {
        .id = "s184728",
        .firstname = "Tommaso",
        .lastname = "Ricci",
        .birthdate = {
            .day = 10,
            .month = 7,
            .year = 1992
        },
        .gender = MALE
    };

    return EXIT_SUCCESS;
}

void die(const char *format, ...) {
    va_list args;
    va_start (args, format);

    vfprintf(stderr, format, args);

    va_end (args);
    exit(EXIT_FAILURE);
}

生成文件:

NAME= es3
BIN= bin
SRC= src
EXE:= $(BIN)/$(NAME)
INPUT= input.txt

#RM=rm -rf
#CC=gcc

OBJS:= $(BIN)/$(NAME).o
FLAGS= -std=c11 -Wall -Wextra -pedantic

all: $(EXE)
$(EXE): $(OBJS)
    $(CC) $(FLAGS) $(OBJS) -o $(EXE)

$(BIN)/$(NAME).o: $(SRC)/$(NAME).c
    $(CC) $(FLAGS) -c $(SRC)/$(NAME).c -o $(BIN)/$(NAME).o

.PHONY: clean
clean:
    $(RM) $(EXE) $(OBJS)

.PHONY: run
run: $(EXE)
    @$(EXE) $(INPUT)

每个变量的初始值设定项都存在,但它仍然显示 missing initializer

gcc 输出:

$ make
cc -std=c11 -Wall -Wextra -pedantic -c src/es3.c -o bin/es3.o
src/es3.c: In function ‘main’:
src/es3.c:22:9: warning: missing initializer for field ‘lastname’ of ‘struct person’ [-Wmissing-field-initializers]
         .lastname = "Ricci",
         ^
In file included from src/es3.c:9:0:
src/student/student.h:20:8: note: ‘lastname’ declared here
  char *lastname;
        ^
src/es3.c:23:9: warning: missing initializer for field ‘birthdate’ of ‘struct person’ [-Wmissing-field-initializers]
         .birthdate = {
         ^
In file included from src/es3.c:9:0:
src/student/student.h:21:9: note: ‘birthdate’ declared here
  date_t birthdate;
         ^
src/es3.c:28:9: warning: missing initializer for field ‘gender’ of ‘struct person’ [-Wmissing-field-initializers]
         .gender = MALE
         ^
In file included from src/es3.c:9:0:
src/student/student.h:22:11: note: ‘gender’ declared here
  gender_t gender;
           ^
src/es3.c:19:15: warning: unused variable ‘student’ [-Wunused-variable]
     student_t student = {
               ^
cc -std=c11 -Wall -Wextra -pedantic bin/es3.o -o bin/es3

如果我理解正确,: 表示法已过时

我在 Cygwin64 上使用 gcc version 4.9.3 (GCC)

我发现的可能的相关问题,但没有解决我的问题:

C11 section 6.7.2.1p13 状态:

An unnamed member whose type specifier is a structure specifier with no tag is called an anonymous structure; an unnamed member whose type specifier is a union specifier with no tag is called an anonymous union. The members of an anonymous structure or union are considered to be members of the containing structure or union. This applies recursively if the containing structure or union is also anonymous.

看来我们都误读了这一点(感谢 Dror K 指出这一点)。您的代码的无标记版本应如下所示:

typedef struct student {
    char id[IDSIZE];

    struct { // <--- note the lack of tag here <---
        char *firstname;
        char *lastname;
        date_t birthdate;
        gender_t gender;
    };
} student_t;

尽管如此,如果我们能找到表明您的编译器支持 C11 的文档,我们只能断定您的编译器支持 C11。唉,当我 运行 进入另一个与 C11 相关的问题时,我试图在早些时候找到这样的文档,但似乎 Cygwin 文档没有任何 C11 支持。如果您需要 C11 支持,您可能需要考虑在 Windows 上使用 llvm/clang。

更改我的 header 代码已解决。

我尝试做的不是标准的,但是 implementation-specific 到 gcc (我认为)

这段代码现在可以运行了,它不再给出初始化错误:

#ifndef STUDENT_H
#define STUDENT_H

#define IDSIZE 7 + 1 // 7x char + '[=10=]' terminator

typedef enum gender {
    MALE = 'M',
    FEMALE = 'F',
    OTHER = 'O'
} gender_t;

typedef struct date {
    short day;
    short month;
    int year;
} date_t;

typedef struct student {
    char id[IDSIZE];
    char *firstname;
    char *lastname;
    date_t birthdate;
    gender_t gender;
} student_t;

#endif

另请参阅此处以获取 GCC 参考:https://gcc.gnu.org/onlinedocs/gcc/Unnamed-Fields.html