如何解决采用结构的函数的循环依赖问题?
How to solve this circular dependency issue with functions taking structs?
我正在尝试解决一个 header 函数中的问题,该函数需要一个结构作为参数,该结构包含与函数相同 header 的结构。这是代码:
Nintendo.h
/**
* Nintendo.h - Nintendo Entertainment System
*
* This header file is the struct that cotains every component of our
* Ninetendo Entertainment System. This is the core file, so to speak,
* that brings together components such as the CPU, PPU, and APU, along
* with some other smaller components.
*/
#ifndef _NINTENDO_H
#define _NINTENDO_H
#include "Registers.h"
typedef struct Nintendo
{
Registers reg;
} Nintendo;
#endif /* _NINTENDO_H */
Registers.h
#ifndef _REGISTERS_H
#define _REGISTERS_H
#include "Constants.h"
#include "Nintendo.h"
typedef struct Registers
{
/* Special Purpose Registers */
Uint16 pc; /* Program Counter */
Uint8 sp; /* Stack Pointer */
/* Bit 7 - Negative Flag N
Bit 6 - Overflow Flag V
Bit 5 - Unused
Bit 4 - Break Command B
Bit 3 - Decimal Mode D
Bit 2 - Interrupt Disable I
Bit 1 - Zero Flag Z
Bit 0 - Carry Flag C
*/
Uint8 p; /* Processor Status */
/* General Purpose Registers */
Uint8 a; /* Accumulator */
Uint8 x;
Uint8 y;
} Registers;
void InitializeRegisters(Nintendo *nes);
#endif /* _REGISTERS_H */
如您所见,'InitializeRegisters' 函数将 Nintendo 结构作为参数,但 Nintendo 结构在其定义中包含 Registers 结构。这会导致循环依赖问题。
我知道我可以通过使参数接受寄存器* 并只传递 &Nintendo.reg 来解决这个问题,但我不想那样做。
这是错误输出:
In file included from source/Nintendo.h:13:
source/Registers.h:31:26: error: unknown type name 'Nintendo'
void InitializeRegisters(Nintendo *nes);
^
1 error generated.
In file included from source/Registers.h:5:
source/Nintendo.h:17:5: error: unknown type name 'Registers'
Registers reg;
^
1 error generated.
/bin/ld: /bin/../lib64/gcc/x86_64-pc-linux-gnu/8.2.0/../../../../lib64/Scrt1.o: in function `_start':
(.text+0x24): undefined reference to `main'
clang-6.0: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [Makefile:2: test] Error 1
最简单的答案是添加以下行:
typedef struct Nintendo Nintendo;
接近 registers.h 的顶部(对头文件使用大小写混合是一个非常糟糕的主意)。 C的一个特点是typedef语句可以重复,只要它们都是一致的,作为一个"forward declaration",这就是你所需要的。
如果您想变态,可以将其放在 #ifndef 行上方的 nintendo.h 中,但如果您喜欢的话,还有其他方法可以让您开心。
我正在尝试解决一个 header 函数中的问题,该函数需要一个结构作为参数,该结构包含与函数相同 header 的结构。这是代码:
Nintendo.h
/**
* Nintendo.h - Nintendo Entertainment System
*
* This header file is the struct that cotains every component of our
* Ninetendo Entertainment System. This is the core file, so to speak,
* that brings together components such as the CPU, PPU, and APU, along
* with some other smaller components.
*/
#ifndef _NINTENDO_H
#define _NINTENDO_H
#include "Registers.h"
typedef struct Nintendo
{
Registers reg;
} Nintendo;
#endif /* _NINTENDO_H */
Registers.h
#ifndef _REGISTERS_H
#define _REGISTERS_H
#include "Constants.h"
#include "Nintendo.h"
typedef struct Registers
{
/* Special Purpose Registers */
Uint16 pc; /* Program Counter */
Uint8 sp; /* Stack Pointer */
/* Bit 7 - Negative Flag N
Bit 6 - Overflow Flag V
Bit 5 - Unused
Bit 4 - Break Command B
Bit 3 - Decimal Mode D
Bit 2 - Interrupt Disable I
Bit 1 - Zero Flag Z
Bit 0 - Carry Flag C
*/
Uint8 p; /* Processor Status */
/* General Purpose Registers */
Uint8 a; /* Accumulator */
Uint8 x;
Uint8 y;
} Registers;
void InitializeRegisters(Nintendo *nes);
#endif /* _REGISTERS_H */
如您所见,'InitializeRegisters' 函数将 Nintendo 结构作为参数,但 Nintendo 结构在其定义中包含 Registers 结构。这会导致循环依赖问题。
我知道我可以通过使参数接受寄存器* 并只传递 &Nintendo.reg 来解决这个问题,但我不想那样做。
这是错误输出:
In file included from source/Nintendo.h:13:
source/Registers.h:31:26: error: unknown type name 'Nintendo'
void InitializeRegisters(Nintendo *nes);
^
1 error generated.
In file included from source/Registers.h:5:
source/Nintendo.h:17:5: error: unknown type name 'Registers'
Registers reg;
^
1 error generated.
/bin/ld: /bin/../lib64/gcc/x86_64-pc-linux-gnu/8.2.0/../../../../lib64/Scrt1.o: in function `_start':
(.text+0x24): undefined reference to `main'
clang-6.0: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [Makefile:2: test] Error 1
最简单的答案是添加以下行:
typedef struct Nintendo Nintendo;
接近 registers.h 的顶部(对头文件使用大小写混合是一个非常糟糕的主意)。 C的一个特点是typedef语句可以重复,只要它们都是一致的,作为一个"forward declaration",这就是你所需要的。
如果您想变态,可以将其放在 #ifndef 行上方的 nintendo.h 中,但如果您喜欢的话,还有其他方法可以让您开心。