[英]Passing a struct by reference errors( incomplete struct and redeclaration)
我正在尝试通过引用传递结构,但是无论我做什么我都会遇到错误。 我想我已经完成了原型设计和声明,并且所有指针都搞砸了。
这是我的一个Arduino项目。 该代码在Arduino编译器上可以正常工作,但不能在Pelles C编译器上编译。
#include <stdio.h>
#include <string.h>
#include <stdint.h>
void Fault_Bits_To_Flags(uint8_t Master_Fault_Byte, struct Fault_Flag_Struct *Fault_Flag);
struct Fault_Flag_Struct {
char Fault_Name[30];
uint8_t Fault_State;
};
struct Fault_Flag_Struct Fault_Flag [7];
int main(void) {
uint8_t Master_Fault_Byte = 181;
strcpy(Fault_Flag[0].Fault_Name, "fault 0");
Fault_Flag[0].Fault_State = 1;
strcpy(Fault_Flag[1]....
strcpy(Fault_Flag[2]....
strcpy(Fault_Flag[3]....
strcpy(Fault_Flag[4]....
Fault_Bits_To_Flags( Master_Fault_Byte, *Fault_Flag);
return 0;
}
//Puts 8 bits from single byte into 8 separate bytes (flags)//
void Fault_Bits_To_Flags(uint8_t Master_Fault_Byte, struct Fault_Flag_Struct *Fault_Flag) {
for ( int i = 0; i < 8; i++ )
{
Fault_Flag[i].Fault_State = (Master_Fault_Byte >> i) & 1;
}
}
错误#2140:在“ Fault_Bits_To_Flags”的参数2中键入错误;
预期为“(不完整)struct Fault_Flag_Struct *”,但发现为“ struct
Fault_Flag_Struct”。错误#2120:重新声明了“ Fault_Bits_To_Flags”,先前在Reference.c(4)上进行了声明; 预期为'void function(unsigned char,(incomplete)struct Fault_Flag_Struct *)',但是找到了'void function(unsigned char,struct Fault_Flag_Struct * )'。 错误代码:1 *
函数原型的参数列表中的参数声明的范围终止于函数声明器的末尾。 与C ++相反,没有C语言中详尽的类型说明符这样的概念。
来自C标准(6.2.1标识符范围)
- ...如果声明标识符的声明器或类型说明符出现在函数原型的参数声明列表中(不是函数定义的一部分),则标识符具有函数原型范围,该范围终止于函数声明符的末尾
因此,函数原型中使用的类型说明符struct Fault_Flag_Struct
void Fault_Bits_To_Flags(uint8_t Master_Fault_Byte, struct
Fault_Flag_Struct *Fault_Flag);
表示与函数原型后的声明相比不同的实体
struct Fault_Flag_Struct {
char Fault_Name[30];
uint8_t Fault_State;
};
因此,您必须交换声明的位置。
也这个电话
Fault_Bits_To_Flags( Master_Fault_Byte, *Fault_Flag);
是无效的,因为表达式的类型*Fault_Flag
是struct Fault_Flag_Struct
而函数期望类型struct Fault_Flag_Struct *
。 那是要传递对象本身,而不是指向struct Fault_Flag_Struct
类型的对象的指针。
显示的代码中有两个问题。
首先是因为C对于结构定义有一些奇怪的规则。 在C 2018 6.7.2.3 4中,一个规则是具有相同标签( struct
名称在struct
之后)的struct
声明只有在具有相同范围的情况下才声明相同类型(具有该名称的结构类型):
具有相同范围并使用相同标记的所有结构,联合或枚举类型的声明都声明相同的类型。…
在函数声明中声明结构时,如下所示:
void foo(struct X *p);
那么X
的范围就是函数原型范围 。 根据6.2.1 4,此作用域在函数声明的末尾结束。 然后,当您稍后定义结构时,如下所示:
struct X { int q; }
它是在一个不同的范围,并且,按照上述规则,在struct X
中的函数声明是不是同一类型的struct X
在后面的定义。 解决此问题的一种方法是在函数声明之前移动结构定义。 只需在函数声明之前声明结构标记即可,例如:
struct X;
void foo(struct X *p);
为了完全了解这里发生的事情,我们应该考虑另外两个问题。 一个问题是,我们可以将struct X
放在两个不同的转换单元中(分别编译不同的源文件),并允许从一个定义了struct X
单元中调用用一个struct X *
参数定义的struct X
。 这是因为,尽管两个转换单元中的两个struct X
类型不同,但是它们是兼容的 。 6.2.7 1说:
…此外,在以下情况下,在单独的翻译单元中声明的两个结构,联合或枚举类型是兼容的:
奇怪的是,该规则仅适用于在单独的翻译单元中声明的结构。 如果在一个翻译单元中定义struct X
之前定义void foo(struct X *p { … }
,它们是不同且不兼容的类型,但是,如果我们在单独的单元中定义它们,则它们是兼容类型!
第二个问题是当结构声明具有单独的作用域时,此代码如何工作:
struct X;
void foo(struct X *p);
第一个struct X
具有文件范围 (根据6.2.1 4),第二个struct X
具有函数原型范围 。 6.7.2.3 4中的规则仅在声明具有相同范围的情况下适用,因此不会说这些声明相同的struct X
相反,在6.7.2.3 9中有另一个规则:
如果以struct-or-union标识符或
enum
标识符形式的类型说明符不是上述形式之一的一部分而出现,并且该标识符的声明作为标记可见,则它指定与其他声明相同的类型,并且不重新声明标签。
(“以上表格”是定义或独立的声明。)这会使函数声明中的struct X
在先前的文件作用域struct X
指定相同的类型之后。
第二个错误是在此语句中传递给函数的第二个参数中:
Fault_Bits_To_Flags( Master_Fault_Byte, *Fault_Flag);
Fault_Flag
是一个数组,因此*Fault_Flag
是该数组的第一个元素。 这是一个结构,而不是指针。 要将指针传递到数组的第一个元素,请使用:
Fault_Bits_To_Flags( Master_Fault_Byte, Fault_Flag);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.