Видимо NULL не известен во включенных файлах - PullRequest
0 голосов
/ 21 декабря 2018

У меня странная проблема:

У меня основной, начинающийся с:

#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"

... но во включенном файле:

#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}
};

Мне нужно переопределить NULL, в противном случае я получаю сообщение об ошибке: "error: 'NULL' здесь не объявлено (не в функции)".

Примечание: NULL определяется в основном файле;если я пытаюсь #define это, я получаю: "warning:" NULL "переопределено"

Исправление тривиально, но я не понимаю, что происходит.Может кто-нибудь пролить свет?

Ответы [ 5 ]

0 голосов
/ 21 декабря 2018

NULL определяется в библиотеке <stddef.h>.

0 голосов
/ 21 декабря 2018

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

Т.е. у вас есть файл заголовка без необходимого #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

И тогда у вас есть два модуля компиляции, но только один из них включает соответствующий заголовок:

// 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

Единственное надежное решение - включить все необходимые заголовкив самом проблематичном заголовке.

Поскольку компилируются только файлы .c, ваш компилятор не будет заботиться о том, что отсутствуют пропуски включений в файлах .h, но в таких случаях в средах разработки, таких как Visual Studio или Eclipse, часто отображаются предупреждающие сообщения..

В качестве примечания:

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}
};

- это переменная, которая будет создана в каждом модуле компиляции, который включает файл заголовка.Это означает, что вы, вероятно, также получите ошибки компоновщика, говорящие о наличии дублирующихся переменных.

0 голосов
/ 21 декабря 2018

Я согласен с предыдущим ответом, но чтобы попытаться объяснить вашу проблему:

, если вы #include stdlib.h , тогда parse.h, где NULL (пере) определен, у вас естьпереопределение, потому что NULL уже определен в stdlib

, если в другом файле вы #include parse.h , но не stdlib.h, вам нужно определить NULL в синтаксическом анализе.h иначе это не определено

, если вы действительно хотите использовать NULL в parse.h, вам нужно #include stdlib внутри, но для меня лучший способ - не использовать NULL

0 голосов
/ 21 декабря 2018

Переопределение макроса здесь неверно.NULL - это имя, зарезервированное этими заголовками, и его определение перед включением заголовка, определяющего его, вызывает неопределенное поведение.

Желательно включить минимальные необходимые заголовки в вашсобственные заголовки.

Если NULL и такие типы, как size_t - это все, что вам нужно, включайте только <stddef.h>.

0 голосов
/ 21 декабря 2018

Не переопределять его.

Просто включите <stdlib.h> в заголовочные файлы

Также не определяйте никакие функции и данные в заголовочных файлах.Только объявления типов, внешние переменные, объявления функций и статические встроенные функции, если они используются во многих файлах Си.

...