Dereferencing Pointer to Incomplete Type Error in C

Jay Shaw Oct 12, 2023
  1. Causes of the dereferencing pointer to incomplete type Error in C
  2. Incomplete Types in C
  3. Referencing and Dereferencing a Pointer in C
  4. Solve the dereferencing pointer to incomplete type Error in C
  5. Conclusion
Dereferencing Pointer to Incomplete Type Error in C

It is known that a pointer is used to store the address of values stored inside a variable. This pointer variable can be referenced to a variable to get its address or dereferenced to access its value.

But when this pointer needs to be seen or edited, it must be dereferenced. When this dereferencing is done through a declared but not defined type, it throws the error dereferencing pointer to incomplete type.

Causes of the dereferencing pointer to incomplete type Error in C

This error is caused when the compiler comes across a pointer being dereferenced to a struct. When the compiler moves towards the struct, it finds it incomplete, i.e., not defined properly.

The compiler throws different errors when an undefined struct is called to deference a pointer. The type of error encountered depends on the compiler used.

the dereferencing pointer to incomplete type Error in GCC Compiler

For example, an undefined struct looks like this:

struct circle {
  int length;
};
int main() {
  struct round *x = 0;
  *x;
}

In the above C program, it can be observed that a struct circle is constructed, but the struct called inside the main function has the name round.

Inside the main function, an object pointer *x is created from the struct round. Lastly, the pointer object is called.

Here, an incomplete struct is used as if it is a complete struct, which causes the compiler to throw the error.

1035906452/source.c: In function 'main':
1035906452/source.c:6:5: error: dereferencing pointer to incomplete type 'struct round'
     *x;
     ^~

It can be observed that the compiler throws the error dereferencing pointer to incomplete type.

Normally, C will find the name of the struct which was put in; if the original struct is not found, this would usually appear. It will also appear if you point a pointer pointed into that pointer.

This error typically appears if the name of your struct is different from the initialization of your struct in the code.

A struct can also throw errors when given an alias that the compiler cannot read, but that does not happen with every compiler.

the dereferencing pointer to incomplete type Error in Clang Compiler

This is encountered when the same code is run through a Clang compiler.

1790191360/source.c:6:5: error: incomplete type 'struct round' where a complete type is required
    *x;
    ^
1790191360/source.c:5:12: note: forward declaration of 'struct round'
    struct round *x = 0;
           ^
1790191360/source.c:6:5: warning: expression result unused [-Wunused-value]
    *x;
    ^~
1 warning and 1 error generated.

Here, the compiler calls out the incomplete struct but leaves the dereferenced pointer as a warning instead of an error.

Understanding why the error dereferencing pointer to incomplete type happens requires knowing two concepts.

  1. What are incomplete types?
  2. What does dereferencing a pointer mean?

Incomplete Types in C

A type declared but not specified is incomplete (in the case of struct types).

Typos in type names, which prevent the compiler from matching one name to the other, are a common cause of incomplete type errors in the C language (like in matching the declaration to the definition).

It is a misconception to think that an incomplete type is a missing type. Incomplete types can occur outside struct too.

Three scenarios cause incomplete type:

  1. A struct type with no members.
  2. A union type with no members.
  3. An array that is declared but no element is inserted.

Create an Incomplete Type and Define It

A struct or a type that is similar needs to be specified with the information lacking to complete an incomplete type.

The creation and completion of the incomplete types are demonstrated in the examples below.

Declare a structure type but omit the members to produce an incomplete structure type. The x pointer in this illustration points to an incomplete structure type named library.

struct library *x;

Declare the same structure type later in the same scope with its members provided to complete an incomplete structure type.

struct library {
  int book_id;
  char book_name[50];
}

To create an array of incomplete types, declare an array type without specifying its repetition count. For instance:

char book_name[]; /* book_name has incomplete type */

Declare the same name later in the same scope with its repetition count set to finish an incomplete array type.

char book_name[25]; /* book_name now has complete type */

Once we have understood how incomplete types are completed, we can go to the second part of solving the dereferencing pointer to incomplete type error.

Referencing and Dereferencing a Pointer in C

The function of a pointer is to store the address of a value, which means it stores a reference to something. The object to which a pointer point is called a pointee.

Referencing a Pointer in C

There are two distinct stages involved in allocating a pointer and a pointee to which it will point. The pointer/pointee structure can be thought of as having two levels of operation.

Everything needs to be set up on both levels for it to work. The most frequent mistake is to focus on writing code that manipulates the pointer level while neglecting to set up the pointee level.

Pointer operations that do not contact the pointees are sometimes referred to as “shallow” operations, while those that do are referred to as “deep” operations.

Consider the following code:

A pointer ptr_a is created inside the main function. This pointer is created but cannot store something unless a pointee or a memory chunk is allocated.

The allocation of memory is done by malloc, and the size given is equivalent to data type int.

void main() {
  int* ptr_a;  // Allocate the pointer

  ptr_a = malloc(
      sizeof(int));  // Allocate an int pointee, and set ptr_a to point to it
}

C++ code:

int main() {
  int* ptr_a;  // Allocate the pointer ptr_a

  ptr_a = new int;  // Allocate an int pointee, and set ptr_a to point to it
}

Dereferencing a Pointer in C

Dereference operations begin at the pointer and follow up to the pointee. The objective could be to examine or modify the pointee state.

A pointer can only be dereferenced if it has a pointee; the pointee must also be allocated before the pointer can be made to point at it. Forgetting to set up the pointee is the most frequent mistake in pointer programs.

Failure in code to successfully dereference a pointer is the most common runtime crash. The runtime system in Java flags the issue of improper dereferences with minor warnings.

In compiled languages like C and C++, a bad dereference can cause a crash or cause spontaneous memory corruption. This makes it challenging to find pointer issues in compiled languages.

C code:

Once the memory is allocated and pointed towards pointer ptr_a, a value is stored inside it by dereferencing it.

void main() {
  int* ptr_a;

  ptr_a = malloc(
      sizeof(int));  // Allocate an int pointee, and set ptr_a to point to it

  *ptr_a = 42;  // Dereference ptr_a to store 42 in its pointee
}

C++ code:

int main() {
  int* ptr_a;  // Allocate the pointers

  ptr_a = new int;  // Allocate an int pointee, and set ptr_a to point to it

  *ptr_a = 42;  // Dereference ptr_a to store 42 in its pointee
}

Shared Pointers in C

When two pointers are assigned to the same pointee, they will both point there. As a result, y points to the same pointee as x when y = x.

The pointees are unaffected by pointer assignment.

It only modifies one pointer to share the same reference as another. After the pointer assignment, the two pointers are considered “sharing” the pointee.

C code:

void main() {
  int* ptr_a;
  int* ptr_b;

  ptr_a = malloc(sizeof(int));

  *ptr_a = 42;

  *ptr_b = 13;  // CRASH -- ptr_b does not have a pointee yet

  ptr_b = ptr_a;  // Pointer assignment sets ptr_b to point to ptr_a's pointee

  *ptr_b = 13;  // Dereference ptr_b to store 13 in its (shared) pointee
}

We have understood the two concepts behind solving the dereferencing pointer to incomplete type error. We will now look at the codes that encounter the error and how to solve the issue.

Solve the dereferencing pointer to incomplete type Error in C

The below program has a struct rectangle with an integer member length. The name of the struct is deliberately made different than the one inside the main function to create an incomplete type.

Inside the main function, the pointer *a is created and allocated memory of the struct rectangle size, and then it is pointed towards it.

Then the pointer is used to dereference the struct member length to store a value inside it. As the struct is of incomplete type, it must throw a dereferencing pointer to incomplete type error.

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

struct rectangle {
  int length;
};

int main() {
  struct square *a;
  a = (struct rectngle *)malloc(sizeof(struct rectngle));
  a->length = 33;
  printf("%d", *a);
}

Output:

1647679200/source.c: In function 'main':
1647679200/source.c:10:38: error: invalid application of 'sizeof' to incomplete type 'struct rectngle'
  a = (struct rectngle*)malloc(sizeof(struct rectngle));
                                      ^~~~~~
1647679200/source.c:11:3: error: dereferencing pointer to incomplete type 'struct square'
  a->length = 33;
   ^~

The incomplete type must be completed to resolve this issue, which in this case is the struct rectngle.

These changes must be made to complete an incomplete struct and dereference its members through a pointer inside the main function.

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

struct rectangle {  // a struct rectngle is created
  int length;
};

int main() {
  struct rectangle *a;  // name of struct inside main() is same as above struct

  a = (struct rectangle *)malloc(sizeof(
      struct rectangle)); /*pointer allocated memory and
                                                                   pointer
                             to pointer 'a'.   */

  a->length = 33;  // pointer deferenced.

  printf("%d", *a);  // value of pointer dereferenced
}

Output:

33

Conclusion

This article sheds light on the error that arises due to dereferencing pointer to incomplete type. After going through this article, the reader can easily reference and deference pointers and complete incomplete types.

Related Article - C Error