Почему работает struct, а typedef struct нет? - PullRequest
2 голосов
/ 26 февраля 2020

У меня проблема с моим кодом.

Вот мое демо:

Моя файловая структура

├── include
│   ├── link.h
│   └── token.h
└── src
    ├── CMakeLists.txt
    └── main.c
//token.h

#ifndef __TOKEN_H__
#define __TOKEN_H__
#include <stdio.h>
#include "link.h"

typedef struct Token{
    char val[30];
}token;

#endif
//link.h

#ifndef __LINKLIST_H__
#define __LINKLIST_H__
#include <stdio.h>
#include "token.h"

typedef struct Linklist{
    token* elem;          
    struct Linklist *next;  
}linklist;

#endif
//main.c

#include <stdio.h>
#include "token.h"
#include "link.h"
#include <stdlib.h>
#include <string.h>

int main(){
    linklist* head = (linklist*)malloc(sizeof(linklist));
    head->elem = (token*)malloc(sizeof(token));
    strcpy(head->elem->val, "111");
    printf("%s\n", head->elem->val);
}
//CMakeLists.txt
cmake_minimum_required(VERSION 3.0.0)
project(test VERSION 0.1.0)

include_directories(../include)

add_executable(test main.c)

Введите файл sr c и скомпилируйте это демо

mkdir build && cd build 
cmake ..
make

Затем возникает одна ошибка:

error: 
      unknown type name 'token'
    token* elem;          
    ^
1 error generated.

Но мы не используем typedef, просто используем struct Token, все будет хорошо.

Версия модификации:

//token.h

struct Token{
    char val[30];
};

//link.h

typedef struct Linklist{
    struct Token* elem;          
    struct Linklist *next; 
}linklist;
//main.c

head->elem = (struct Token*)malloc(sizeof(struct Token));

Я хочу спросить, почему возникает такая ситуация?

Ответы [ 2 ]

4 голосов
/ 26 февраля 2020

У вас есть циклическая зависимость включения, и вам нужно разорвать этот круг.

Обычный способ сделать это - перестать включать файлы в заголовочный файл там, где это действительно не нужно, и использовать forward. объявления при необходимости.

Один простой способ с вашим текущим кодом - просто не включать link.h в tokens.h, поскольку struct Linklist или linklist не используется в заголовке token.h file:

#ifndef TOKEN_H
#define TOKEN_H

typedef struct Token{
    char val[30];
}token;

#endif

Обратите внимание, что есть директивы no #include выше.


В другой заметке я изменил имена макросов header-guard, потому что все символы с двойным подчеркиванием зарезервированы в C, вы не должны определять такие символы или имена самостоятельно (как макросы или как-то иначе).

С эта ссылка на зарезервированные идентификаторы :

Все идентификаторы, которые начинаются с подчеркивания, за которым следует заглавная буква или другое подчеркивание

[Выделение мое]

0 голосов
/ 26 февраля 2020

Это происходит потому, что вы создали circular dependency, включив link.h в token.h и наоборот.

Если вы вырезали #include <link.h> из token.h, все должно работать нормально.

Когда вы #include token.h в своей основной, вот что произойдет:

#ifndef __TOKEN_H__ //not defined
#define __TOKEN_H__
#include <stdio.h>
//#include "link.h" expands to:

  #ifndef __LINKLIST_H__ //not defined
  #define __LINKLIST_H__
  #include <stdio.h>
  //#include "token.h" expands to:

    #ifndef __TOKEN_H__ //defined
    #endif

  typedef struct Linklist{
      token* elem;          // token was not declared yet: ERROR
      struct Linklist *next;  
  }linklist;

  #endif 

typedef struct Token{
    char val[30];
}token;

#endif
...