显然在包含的文件中不知道NULL

Zio*_*yte 2 c gcc c-preprocessor

我面临一个奇怪的问题:

我有一个主要的开头:

#include <stdlib.h>     /* this defines NULL */
#include <stdio.h>      /* ditto */
#include <fcntl.h>
#include <ctype.h>      /* ditto */
#include <unistd.h>     /* ditto */

#include <linux/input.h>

#include <string.h>     /* ditto */
#include <sys/ioctl.h>

#include "parse.h"
Run Code Online (Sandbox Code Playgroud)

...但在包含的文件中:

#define NULL ((void*)0)  /* I need this! */

struct parse_key {
    char *name;
    unsigned int value;
} keynames[] = {
    {"KEY_RESERVED", 0},
    {"KEY_ESC", 1},
    {"KEY_1", 2},
    {"KEY_2", 3},
    ...
    {"KEY_MAX", 0x2ff},
    {NULL, 0}
};
Run Code Online (Sandbox Code Playgroud)

我需要重新定义NULL,否则我得到错误:"错误:'NULL'在这里未声明(不在函数中)".

注:NULL 主文件中定义; 如果我尝试#define它,我得到:"警告:"NULL"重新定义"

修复是微不足道的,但我不明白发生了什么.有人会发光吗?

P__*_*J__ 6

不要重新定义它.

只需包含<stdlib.h>在头文件中

也不要在头文件中定义任何函数和数据.只有类型声明,外部变量,函数声明和静态内联函数(如果它们在许多C文件中使用).


Gro*_*roo 5

通常,当您在实际头文件中不包含必要的头文件时会发生此问题,但它们会在某些编译单元的头部之前包含在内.

即你没有必要的头文件#include:

// parse.h
#ifndef PARSE_H
#define PARSE_H

struct parse_key
{
    char *name;
    unsigned int value;
}

static inline void key_init(struct parse_key * pk)
{
    pk->name = NULL; // <-- you need it here
}

#endif // PARSE_H
Run Code Online (Sandbox Code Playgroud)

然后你有两个编译单元,但只有一个包含适当的标题:

// something.c
#include <stdlib.h>
#include "parse.h"    // <-- preprocessor inserts this when NULL is already known


// something_else.c
#include "parse.h"    // <-- but in this case, it will not compile
Run Code Online (Sandbox Code Playgroud)

唯一可靠的解决方案是在问题标题本身中包含所有必要的标题.

由于只编译.c文件,因此编译器不会关心.h文件中是否包含.c文件,但是在这些情况下,Visual Studio或Eclipse等IDE通常会显示警告消息.

作为旁注,这:

struct parse_key {
    char *name;
    unsigned int value;
} keynames[] = {
    {"KEY_RESERVED", 0},
    {"KEY_ESC", 1},
    {"KEY_1", 2},
    {"KEY_2", 3},
    ...
    {"KEY_MAX", 0x2ff},
    {NULL, 0}
};
Run Code Online (Sandbox Code Playgroud)

是一个变量,它将在包含头文件的每个编译单元中创建.这意味着您可能还会收到链接器错误,告诉您有重复的变量.