C 语言中的 Dereferencing Pointer to Incomplete Type Error 错误
众所周知,指针用于存储存储在变量中的值的地址。 这个指针变量可以引用一个变量来获取它的地址,或者取消引用来访问它的值。
但是当这个指针需要被查看或编辑时,它必须被解除引用。 当通过已声明但未定义的类型完成此取消引用时,它会抛出错误 dereferencing pointer to incomplete type。
C 中dereferencing pointer to incomplete type Error 的原因
当编译器遇到一个被取消引用到结构的指针时,会导致此错误。 当编译器转向该结构时,它发现它不完整,即未正确定义。
当调用未定义的结构来引用指针时,编译器会抛出不同的错误。 遇到的错误类型取决于所使用的编译器。
GCC 编译器中 dereferencing pointer to incomplete type Error
例如,未定义的结构如下所示:
struct circle {
int length;
};
int main() {
struct round *x = 0;
*x;
}
在上面的C程序中,可以观察到构造了一个 struct circle
,但是在 main
函数内部调用的 struct 的名字是 round 。
在 main 函数内部,一个对象指针 *x
是从 struct round
创建的。 最后,指针对象被调用。
在这里,一个不完整的结构被当作一个完整的结构来使用,这会导致编译器抛出错误。
1035906452/source.c: In function 'main':
1035906452/source.c:6:5: error: dereferencing pointer to incomplete type 'struct round'
*x;
^~
可以观察到编译器抛出错误 dereferencing pointer to incomplete type。
通常,C 会找到放入的结构的名称; 如果找不到原始结构,通常会出现。 如果您将指针指向该指针,它也会出现。
如果您的结构名称与代码中结构的初始化不同,通常会出现此错误。
当给定编译器无法读取的别名时,结构也可能抛出错误,但并非每个编译器都会发生这种情况。
Clang 编译器中 dereferencing pointer to incomplete type Error
当通过 Clang 编译器运行相同的代码时会遇到这种情况。
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.
在这里,编译器调用了不完整的结构,但将取消引用的指针保留为警告而不是错误。
理解为什么会发生错误取消引用指向不完整类型的指针需要了解两个概念。
- 什么是不完整类型?
- 取消引用指针是什么意思?
C 中的不完整类型
声明但未指定的类型是不完整的(在结构类型的情况下)。
类型名称中的拼写错误会阻止编译器将一个名称与另一个名称相匹配,这是 C 语言中不完整类型错误的常见原因(例如将声明与定义相匹配)。
认为不完整类型是缺失类型是一种误解。 不完整的类型也可能出现在 struct
之外。
三种情况导致类型不完整:
- 没有成员的结构类型。
- 没有成员的联合类型。
- 已声明但未插入元素的数组。
创建一个不完整的类型并定义它
需要用缺少的信息来指定类似的结构或类型,以完成不完整的类型。
下面的示例演示了不完整类型的创建和完成。
声明结构类型但省略成员以生成不完整的结构类型。 此图中的 x 指针指向名为库的不完整结构类型。
struct library *x;
稍后在同一范围内声明相同的结构类型,并提供其成员以完成不完整的结构类型。
struct library
{
int book_id;
char book_name[50];
}
要创建不完整类型的数组,请声明一个数组类型而不指定其重复计数。 例如:
char book_name[]; /* book_name has incomplete type */
稍后在相同范围内声明相同的名称,并设置其重复计数以完成不完整的数组类型。
char book_name[25]; /* book_name now has complete type */
一旦我们了解了不完整类型是如何完成的,我们就可以转到解决不完整类型错误的解引用指针的第二部分。
在 C 中引用和取消引用指针
指针的作用是存储一个值的地址,这意味着它存储了对某物的引用。 指针指向的对象称为指针对象。
在 C 中引用指针
分配指针和它将指向的指针对象涉及两个不同的阶段。 指针/被指针结构可以被认为具有两级操作。
一切都需要在两个级别上进行设置才能正常工作。 最常见的错误是专注于编写操纵指针级别的代码,而忽略了设置指针级别。
不接触指针的指针操作有时被称为“浅”操作,而那些被称为“深”操作。
考虑以下代码:
在 main
函数中创建了一个指针 ptr_a 。 这个指针被创建但不能存储一些东西,除非分配了指针或内存块。
内存的分配是由 malloc
完成的,给定的大小相当于数据类型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++ 代码:
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
}
在 C 中取消引用指针
解引用操作从指针开始,一直到指针对象。 目标可能是检查或修改指针状态。
指针只有在有指针时才能被取消引用; 在指针可以指向它之前,还必须分配指针对象。 忘记设置指针对象是指针程序中最常见的错误。
代码中无法成功取消引用指针是最常见的运行时崩溃。 Java 中的运行时系统会用轻微警告标记不正确的取消引用问题。
在 C 和 C++ 等编译语言中,错误的取消引用可能会导致崩溃或自发内存损坏。 这使得在编译语言中查找指针问题变得具有挑战性。
C代码:
一旦分配了内存并指向指针 ptr_a,就会通过取消引用将一个值存储在其中。
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++ 代码:
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
}
C 中的共享指针
当两个指针被分配给同一个指针对象时,它们都会指向那里。 结果,当 y = x
时,y 指向与 x 相同的指针。
指针对象不受指针赋值的影响。
它只修改一个指针以与另一个指针共享相同的引用。 指针赋值后,这两个指针被认为是“共享”指针对象。
C代码:
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
}
我们已经理解了解决不完整类型错误的解引用指针背后的两个概念。 我们现在将查看遇到错误的代码以及如何解决问题。
解决 C 中指向不完整类型错误的取消引用指针 下面的程序有一个具有整数成员长度的结构矩形。 结构的名称故意与 main 函数中的名称不同,以创建不完整的类型。
在 main 函数内部,指针 *a
被创建并分配了 struct rectangle
大小的内存,然后指向它。
然后指针用于取消引用结构成员长度以在其中存储一个值。 由于该结构是不完整类型,它必须抛出指向不完整类型错误的解引用指针。
#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);
}
输出:
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;
^~
必须完成不完整类型才能解决此问题,在本例中为 struct rectngle。
必须进行这些更改以完成不完整的结构并通过主函数内的指针取消引用其成员。
#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
}
输出结果:
33
总结
本文阐明了由于取消引用指向不完整类型的指针而引起的错误。 读完本文后,读者可以轻松地引用和推导指针以及完成不完整的类型。
相关文章
在 C 语言中使用 typedef enum
发布时间:2023/05/07 浏览次数:181 分类:C语言
-
本文介绍了如何在 C 语言中使用 typedef enum。使用 enum 在 C 语言中定义命名整数常量 enum 关键字定义了一种叫做枚举的特殊类型。
C 语言中的 extern 关键字
发布时间:2023/05/07 浏览次数:114 分类:C语言
-
本文介绍了如何在 C 语言中使用 extern 关键字。C 语言中使用 extern 关键字来声明一个在其他文件中定义的变量
C 语言中的 #ifndef
发布时间:2023/05/07 浏览次数:186 分类:C语言
-
本文介绍了如何在 C 语言中使用 ifndef。在 C 语言中使用 ifndef 保护头文件不被多次包含 C 语言中的头文件用于定义同名源文件中实现的函数的接口。