Search code examples
cfunctioncompiler-errorsstructure

Why do I get this error: array type has incomplete element type, type of formal parameter is incomplete?


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?


Solution

  • 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.