2016-09-25 3 views
0

Dies ist die Sprache C. Wenn ich mein folgendes Programm starte, egal wie klein ich gebe, erhalte ich einen Laufzeitsegmentierungsfehler. Bitte helfen Sie mir, die Ursache dafür herauszufinden.Bitfelder mit Segmentierungsfehler

#include <stdio.h> 
#include <stdlib.h> 
struct date 
{ 
unsigned day: 
    5; 
unsigned month: 
    4; 
unsigned year: 
    12; 
}; 
struct emp 
{ 
    char name[10]; 
    struct date d; 
}; 
int compare(const void * a, const void * b) 
{ 
    struct emp *orderA = (struct emp *)a; 
    struct emp *orderB = (struct emp *)b; 
    return ( orderA->d.year - orderB->d.year ); 
} 
int main() 
{ 
    int i; 
    struct emp e[5]; 
    for (i = 0;i < 5;i++) 
    { 
     scanf("%s %d %d %d", e[i].name, e[i].d.day, e[i].d.month, e[i].d.year); 
    } 
    qsort(e, 5, sizeof(struct emp), compare); 
    for (i = 0;i < 5;i++) 
    { 
     printf("%s %d %d %d\n", e[i].name, e[i].d.day, e[i].d.month, e[i].d.year); 
    } 
    return 0; 
} 
+0

Bitfelder in C haben eine Menge Macken, also würde ich empfehlen, dass Sie sie vermeiden, wenn Sie sie wirklich brauchen. Für den obigen Code könnten Sie 'struct date {uint8_t day; uint8_t Monat; uint16_t Jahr; }; ', und Sie erhalten wahrscheinlich die gleiche Größe Struktur, die gleich oder leistungsfähiger und vielseitiger ist (Sie können die Adresse der Mitglieder nehmen). – user694733

Antwort

5

Wenn Sie scanf() wollen Ihre Sachen scannen, müssen Sie Adressen Sachen passieren, nicht das eigentliche Material. (Wenn Sie sich nicht über die Adresse von etwas scanf(), wie kann dann scanf() Speicher ein Wert in das?)

nun in C, wenn Sie auf ein Array verweisen wie e[i].name Sie beziehen sich tatsächlich auf die Adresse der erstes Element des Arrays, so dass Sie nichts Besonderes tun müssen. (Außer vorsichtig sein, um nicht mehr als 9 Zeichen eingeben für Namen, wh00ps, das ist extrem unsicher, seien Sie vorsichtig!)

Aber mit ganzen Zahlen, wie e[i].d.day etc, können Sie nicht nur die int passieren, wie es ist, Weil scanf() Zeiger erwartet, so wird es Ihre int als Zeiger auf eine int behandeln, so wird es dem Benutzer erlauben, eine Nummer einzugeben, und dann wird es versuchen, die Nummer an der Stelle zu speichern, die von diesem Zeiger, der nur einige ist zufällige Position im Speicher und somit der Segfault. So

, wenn Sie eine int scannen möchten, müssen Sie die Adresse des int passieren, wie folgt aus: &e[i].d.day

Abgesehen davon, dass, wenn die ganze Zahl ein Feld eines Datensatzes ist, kann man nicht seine Adresse übernehmen, Weil es keine eigene Adresse hat, lebt es innerhalb einiger Bits, die an einer Adresse gespeichert sind.

Also, ich fürchte, Sie werden eine spezielle Funktion für das Lesen dieser struct date s von Ihnen haben zu schreiben, die einzelnen int s zu erklären haben, geben ihre Adressen zu scanf(), und speichern Sie dann die resultierenden Werte in ein struct date.