overloood overloood - 2 months ago 24
C Question

Bit fields giving segmentation fault

This is C language. When I run my following program, no matter how small values I give, I get runtime segmentation fault error. Please help me find out the cause of this.

#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;
}

Answer

When you want scanf() to scan your stuff, you have to pass addresses of stuff, not the actual stuff. (If you do not pass the address of something to scanf(), then how can scanf() store a value in it?)

Now, in C when you refer to an array such as e[i].name you are actually referring to the address of the first element of the array, so you do not have to do anything special about that. (Besides to be careful to not enter more than 9 characters for name, wh00ps, that's extremely unsafe, be careful!)

But with integers, such as e[i].d.day etc, you can't just pass the int as it is, because scanf() expects pointers, so it will treat your int as a pointer to an int, so it will allow the user to enter a number, and then it will try to store the number at the location pointed by that pointer, which is just some random location in memory, and thus the segfault.

So, when you want to scan an int, you have to pass the address of the int, like this: &e[i].d.day

Except that when the integer is a field of a record, you cannot take its address, because it does not have an address of its own, it lives within some bits stored at an address.

So, I am afraid you are going to have to write a special function for reading those struct dates of yours, which will have to declare individual ints, pass their addresses to scanf(), and then store the resulting values in a struct date.