Как решить эту проблему циклической зависимости с помощью функций, принимающих структуры? - PullRequest
0 голосов
/ 06 сентября 2018

Я пытаюсь решить проблему с функцией в одном заголовке, требующей структуру в качестве параметра, который включает структуру из того же заголовка, что и функция. Вот код:

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

1 Ответ

0 голосов
/ 06 сентября 2018

Самый простой ответ - добавить строку:

typedef struct Nintendo Nintendo;

в верхней части registers.h (использование смешанного регистра для заголовочных файлов - очень плохая идея). Особенностью C является то, что операторы typedef могут повторяться при условии, что они все непротиворечивы и служат «предварительным объявлением», что вам и требуется.

Если вы хотите быть извращенцем, вы можете поместить его в nintendo.h над строкой #ifndef, но есть и другие способы получить удовольствие, если это ваше дело.

...