C99 | (BItfield)无法使用name1.name2.variable选择Struct中的Struct

时间:2019-01-12 18:01:47

标签: c arrays struct c99

如何解决此错误?我想拥有一个可以在其中扫描“学生”数据并因此使用结构的数组。问题是,另一个结构中的位域结构失败。

有什么方法可以解决此问题,而无需更改大多数代码结构?只想解决,可以选择位域(天,月等)。

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

#define MAX 10
#define MAXCHAR 30

char comma;

struct date {
    unsigned int day:5;         
    unsigned int month:4;
    unsigned int year:11;   //funktioniert bis yr 2047;
};

struct student {
        unsigned long matriculation_number;
        char first_name[MAXCHAR];
        char last_name[MAXCHAR];
        struct date birthdate;
}Student[MAX];

/*
void scan_student(void) {
b
} */

int main(void) {

    int i = 0;
    printf("------------------------------\nGeben Sie alle benötigten Daten ein\n");
    printf("Vorname: ");
    fgets(Student[i].first_name, MAXCHAR, stdin);

    printf("Nachname: ");
    fgets(Student[i].last_name, MAXCHAR, stdin);

    printf("Matrikelnummer: ");
    scanf(" %lu", &Student[i].matriculation_number);

    printf("Geburtstdatum (DD.MM.YYYY): ");
    scanf(" %u%c%u%c%u", &Student.birthdate.day, &comma, &Student.birthdate.month, &comma, &Student.birthdate.year);
    printf("\n");


    return EXIT_SUCCESS;
}

错误日志:

student.c: In function ‘main’:
student.c:42:26: error: cannot take address of bit-field ‘day’
     scanf(" %u%c%u%c%u", &Student[i].birthdate.day, &comma, &Student[i].birthdate.month, &comma, &Student[i].birthdate.year);
                          ^
student.c:42:61: error: cannot take address of bit-field ‘month’
     scanf(" %u%c%u%c%u", &Student[i].birthdate.day, &comma, &Student[i].birthdate.month, &comma, &Student[i].birthdate.year);
                                                             ^
student.c:42:98: error: cannot take address of bit-field ‘year’
 &Student[i].birthdate.day, &comma, &Student[i].birthdate.month, &comma, &Student[i].birthdate.year);

2 个答案:

答案 0 :(得分:2)

虽然不能将位域成员传递给scanf,但是可以将临时对象传递给scanf,然后将它们分配到位域而不会出现问题:

unsigned char day = 0, month = 0;
unsigned short year = 0;
scanf(" %hhu%c%hhu%c%hu", &day, &comma, &month, &comma, &year);
Student.birthdate.day = day;
Student.birthdate.month = month;
Student.birthdate.year = year;

请注意,这确实涉及缩小范围,因此您可能拥有成功的scanf,然后无法将其完整值存储在位字段中。

考虑到进一步的注释,请注意,不允许您使用tmp步骤,这对于设置此任务的任何人都是完全不合理的,您根本不能使用scanf。但是,您可以分别读取字符串,然后使用strtoul或类似方法将数字标记转换为可以直接分配到位域中的返回值。我真的不建议这样做,但是如果是分配作业或类似作业的要求,则可以。

根据要求:C11 specification部分7.21.6.1第7段描述了在此示例中使用的长度修饰符hhh。这些允许指定整数类型的长度,其中hhchar的长度,而h是short的长度。将它们与d i o u xX结合使用,可以指定要由(f)scanf读取的所有内置整数类型。

答案 1 :(得分:0)

struct date是使用位域定义的,因此未在字节边界上对齐。由于它不在字节边界上,因此无法使用&运算符获取它的地址。尝试按以下方式重新定义struct date

struct date {
    unsigned char day;
    unsigned char month;
    unsigned short year;
}

这还有一个额外的好处,即允许您将年份存储到65535(而不是2047)。