gcc可能的bug?在带有点表示法的struct中缺少初始化程序

时间:2015-12-05 16:12:49

标签: c gcc struct initialization c11

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

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

这是我的代码。我尝试使用冒号:表示法但我得到了一个过时的初始化程序警告,所以我切换到点.表示法。

它真的只是一个错误,或者我在这里做错了什么?我可以压制这个警告,但我当时认为它不应该在那里。我仔细检查了我的代码,应该是正确的,对吗?编译器应该很开心,不要发出警告。

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

编辑:我试图做的“事情”是C11标准与否? Can I 'extend' a struct in C?

编辑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

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

如果我理解正确,:符号已过时

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

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

2 个答案:

答案 0 :(得分:2)

C11 section 6.7.2.1p13州:

  

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

我们似乎都误读了这一点(谢谢,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。

答案 1 :(得分:0)

解决了我的标题代码问题。

我尝试做的不是标准,而是针对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参考:https://gcc.gnu.org/onlinedocs/gcc/Unnamed-Fields.html