I am working on an assignment which involves creating a program in C to create a student database using array of structures.
Following is my code:
#include<stdio.h>
void accept(int no, struct student arr[20]);
void display(int no, struct student arr[20]);
struct student
{
char name [15];
int rollno;
float marks;
};
int main()
{
int no, n;
printf("Enter the number of students: ");
scanf("%d", &no);
struct student arr[20];
accept(no, arr);
display(no, arr);
}
void accept(int no, struct student arr[20])
{
for(int i=0; i<no; i++)
{
printf("Enter the name of the student: ");
scanf("%s", &arr[i].name);
printf("\nEnter the Roll No: ");
scanf("%d", &arr[i].rollno);
printf("\nEnter the marks: ");
scanf("%f", &arr[i].marks);
}
}
void display(int no, struct student arr[20])
{
for(int i=0; i<no; i++)
{
printf("Name: %s ", arr[i].name);
printf("Roll No: %d", arr[i].rollno);
printf("Marks: %f", arr[i].marks);
}
}
Following are the errors shown on my cmd using gcc:
ass3.c:5:36: error: array type has incomplete element type 'struct student'
void accept(int no, struct student arr[20]);
^~~
ass3.c:5:28: warning: 'struct student' declared inside parameter list will not be visible outside of this definition or declaration
void accept(int no, struct student arr[20]);
^~~~~~~
ass3.c:6:37: error: array type has incomplete element type 'struct student'
void display(int no, struct student arr[20]);
^~~
ass3.c:6:29: warning: 'struct student' declared inside parameter list will not be visible outside of this definition or declaration
void display(int no, struct student arr[20]);
^~~~~~~
ass3.c: In function 'main':
ass3.c:24:16: error: type of formal parameter 2 is incomplete
accept(no, arr);
^~~
ass3.c:25:17: error: type of formal parameter 2 is incomplete
display(no, arr);
^~~
ass3.c:24: confused by earlier errors, bailing out
I am unable to understand what is causing these errors. How can I correct them? I read somewhere that I can solve this by using pointers. How does that work?
Where void accept(int no, struct student arr[20]);
appears, struct student
has not been declared previously. So struct student
is the first time the compiler has seen this structure tag. This serves as a declaration of the tag, and it causes the compiler to create a new type named struct student
.
At this point, the compiler only knows the type exists. It does not know what the members of the structure are, and so it does not know what size the structure is. This is called an incomplete type.
struct student arr[20]
declares arr
to be an array of this type. There is a rule in C 2018 6.7.6.2 1 that the element type of an array may not be incomplete. So the compiler complains that your struct student arr[20]
declares an array with incomplete element type.
Because this is parameter declaration, it will be automatically adjusted to be a pointer. You can have a pointer to an incomplete type; struct student *arr
would be allowed. However, your compiler applies the rule about array element types before the automatic adjustment is applied.
A second problem is the scope of the tag. As noted above, struct student
inside this function declaration declares a new structure tag. This tag has function prototype scope. Its scope ends at the end of the function declaration.
When the compiler later sees the definition of struct student
with the member definitions, that is in a new scope and creates a new instance of struct student
that is separate from the old one. It is a new type that is not compatible with the earlier type. Then it is essentially impossible to call this function in a useful way that conforms to the rules of the C standard. Because the scope of the first struct student
ended, there is no way for a caller of the function to create a struct student
whose address they could pass to the function. Worse, when the function is defined, there is no way for the parameter declaration in that function definition to refer to the same struct student
as the original function declaration.
To fix this, put the definition of struct student
before the declaration of any function that uses it in a parameter declaration, instead of after. Then, when the compiler sees struct student
in a parameter declaration, it will take it as a reference to the existing struct student
type instead of as a declaration of a new type.
Alternatively, you can declare struct student;
before the function declarations. That creates a struct student
type with the tag having file scope. That solves the problem of the type being newly created inside the function declaration, but it does not solve the incomplete element type problem. To solve that, change the parameter declaration from struct student arr[20]
to struct student *arr
.