C 可能的错误?带点表示法的结构中缺少初始值设定项

C 可能的错误?带点表示法的结构中缺少初始值设定项,c,gcc,struct,initialization,c11,C,Gcc,Struct,Initialization,C11,我正在使用这些gcc标志编译我的程序:-std=c11-Wall-Wextra-pedantic 我尝试使用带有字段标签的初始值设定项初始化结构,而不是记住每个字段的正确顺序。然而,我得到了一些我不理解的警告。在另一个问题中,有人声称这可能是一个gccbug。。。我不知道 这是我的密码。我尝试使用冒号:表示法,但我收到一个过时的初始值设定项警告,所以我切换到了点表示法 这真的只是一个bug,还是我做错了什么?我可以压制这个警告,但我认为它本来就不应该在那里。我仔细检查了我的代码,它应该是正确的,

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

我尝试使用带有字段标签的初始值设定项初始化结构,而不是记住每个字段的正确顺序。然而,我得到了一些我不理解的警告。在另一个问题中,有人声称这可能是一个
gcc
bug。。。我不知道

这是我的密码。我尝试使用冒号
表示法,但我收到一个过时的初始值设定项警告,所以我切换到了点
表示法

这真的只是一个bug,还是我做错了什么?我可以压制这个警告,但我认为它本来就不应该在那里。我仔细检查了我的代码,它应该是正确的,对吗?编译器应该很高兴,不要发出警告

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

编辑:我想做的“事情”真的是标准的吗?

编辑2:已解决。见下面我的答案

学生/student.h

#ifndef STUDENT_H
#define STUDENT_H

#define IDSIZE 7 + 1 // 7x char + '\0' 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
/**
 * 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)
$ 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
es3.c

#ifndef STUDENT_H
#define STUDENT_H

#define IDSIZE 7 + 1 // 7x char + '\0' 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
/**
 * 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)
$ 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
每个变量的初始值设定项都存在,但仍然表示
缺少初始值设定项

gcc输出

#ifndef STUDENT_H
#define STUDENT_H

#define IDSIZE 7 + 1 // 7x char + '\0' 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
/**
 * 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)
$ 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版本4.9.3(gcc)

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

    • 指出:

      类型说明符为不带标记的结构说明符的未命名成员称为匿名结构;类型说明符为不带标记的联合说明符的未命名成员称为匿名联合。匿名结构或联合的成员被视为包含结构或联合的成员。如果包含的结构或联合也是匿名的,则递归地应用

      看来我们都误读了这一点(谢谢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;
      
      typedef结构学生{
      字符id[IDSIZE];
      
      struct{/解决了更改头代码的问题

      我试图做的不是标准的,而是特定于
      gcc
      (我想)的实现

      这段代码现在正在运行,不再出现初始化器错误:

      #ifndef STUDENT_H
      #define STUDENT_H
      
      #define IDSIZE 7 + 1 // 7x char + '\0' 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
      参考资料:

      刚刚在普通Windows上试用了
      MinGW
      ,并且刚刚收到关于未使用的variable@Seb您的引用声明:“…其类型说明符是不带标记的结构说明符…”-据我所知,他的结构有一个标记?但是如果我在Windows上运行makefile,
      cmd
      /
      MinGW
      我会得到一个链接器错误LOL@DrorK.你是对的……我不知道我是怎么误读的(好吧,事实上,我是这样认为的……深夜会让我们中最好的人变得愚蠢)。谢谢!:)那么,我没有使用标准功能?:p您的原始代码没有问题。使用
      gcc-std=c11-pedantic errors-Wall-Wextra
      编译就可以了。请注意,当涉及到指定的初始值设定项时,这是gcc中的一个缺陷/错误。我以前编写的只是一个gcc扩展,如果它不可移植,我就不这么做了我想使用它。但我同意,如果GCC支持,它不应该给出警告当你说-std=c11-pedantic时,你要求它不支持非标准扩展。你不可能两种方式都有。