用例#ifdef _MAIN_
Uses cases #ifdef _MAIN_
使用时的主要目标是什么: #ifdef _MAIN_
在 c 程序的头文件中。
这是一个例子:
#ifndef _INTDSPMNG_H_
#define _INTDSPMNG_H_
#include <pthread.h>
typedef struct dspList_t
{
char mesfct[CL_MESFCT+1];
char processus[CL_NOMLOG+1];
char requete_json[CL_MSJSON+1];
char reponse_json[CL_MSJSON+1];
int actif;
}dspList_t;
/* Gestion des erreurs */
#define CV_DSPMNG_OK 0
#define CV_DSPMNG_ERROR 1
#define DELAI_REVEIL_DSPMNG
#ifdef _MAIN_
dspList_t *gDspmngTab = NULL;
int nb_config_dspmng = 0;
PARAM_COM_WEBSRV ParamCom;
#else
extern dspList_t *gDspmngTab;
extern int nb_config_dspmng;
extern PARAM_COM_WEBSRV ParamCom;
#endif
#endif
说明项目结构错误
extern dspList_t *gDspmngTab;
extern int nb_config_dspmng;
extern PARAM_COM_WEBSRV ParamCom;
这些行应该在头文件中。那么所有使用该对象的 .c
文件都应该包含它。只有一个源文件应该定义实际对象。
IMO 代码的作者需要声明,但从未听说过头文件。所以他决定这样做#ifdef
“黑魔法”
习惯做法是在header文件中声明一个object(或函数),并在一个源文件中定义它。例如,给定一个名为 foo
的 object 在名为 bar.c
的文件中定义为 MyType foo = 0;
,header 文件 bar.h
将声明 MyType foo;
.然后每个需要 foo
的源文件将使用 #include "bar.h"
来获取它的声明。
您所询问的代码的作者显然决定将定义和声明放在一起。他们的 header 文件 intdspmng.h
(根据包含防护的名称推测)可以包含在源文件中,并且通常会声明标识符。但是,当他们将其包含在 main.c
或他们指定为主文件的任何内容中时,他们首先定义 _MAIN_
,可能使用 #define _MAIN_
或 #define _MAIN_ 1
。然后,当它们包含 intdspmng.h
时,它会定义标识符而不是仅仅声明它们。
换句话说,那个人可能想“我想把这些东西的声明和定义放在一起,因为这样更容易编辑它们,也更容易看到定义和声明之间的关联。因此,我将编写可以放入 header 文件但仅定义主文件中内容的代码。”
这可能并非完全不合理。然而,他们犯了一个错误。声明的一个目的是检查它们是否与定义相匹配。如果在定义标识符的源文件中,我们还包括声明它们的 header,那么编译器会同时看到声明和定义,如果它们发生冲突,它将报告警告或错误,就像印刷发生错误或类型在一个地方更改,但在另一个地方没有更改。
这可以通过始终包含声明来补救,而仅当 _MAIN_
的定义要求时才包含定义:
extern dspList_t *gDspmngTab;
extern int nb_config_dspmng;
extern PARAM_COM_WEBSRV ParamCom;
#ifdef _MAIN_
dspList_t *gDspmngTab = NULL;
int nb_config_dspmng = 0;
PARAM_COM_WEBSRV ParamCom;
#endif
虽然这弥补了这个不足,但我仍然不会说我推荐这种方法。
另一个问题是,根据 C 标准,以下划线开头后跟大写字母或另一个下划线的标识符是保留的。在一般程序代码中应避免使用它们,尽管编译器和“系统”库可能会使用它们。所以_MAIN_
应该改成别的,比如DefineMainObjects
.
使用时的主要目标是什么: #ifdef _MAIN_
在 c 程序的头文件中。
这是一个例子:
#ifndef _INTDSPMNG_H_
#define _INTDSPMNG_H_
#include <pthread.h>
typedef struct dspList_t
{
char mesfct[CL_MESFCT+1];
char processus[CL_NOMLOG+1];
char requete_json[CL_MSJSON+1];
char reponse_json[CL_MSJSON+1];
int actif;
}dspList_t;
/* Gestion des erreurs */
#define CV_DSPMNG_OK 0
#define CV_DSPMNG_ERROR 1
#define DELAI_REVEIL_DSPMNG
#ifdef _MAIN_
dspList_t *gDspmngTab = NULL;
int nb_config_dspmng = 0;
PARAM_COM_WEBSRV ParamCom;
#else
extern dspList_t *gDspmngTab;
extern int nb_config_dspmng;
extern PARAM_COM_WEBSRV ParamCom;
#endif
#endif
说明项目结构错误
extern dspList_t *gDspmngTab;
extern int nb_config_dspmng;
extern PARAM_COM_WEBSRV ParamCom;
这些行应该在头文件中。那么所有使用该对象的 .c
文件都应该包含它。只有一个源文件应该定义实际对象。
IMO 代码的作者需要声明,但从未听说过头文件。所以他决定这样做#ifdef
“黑魔法”
习惯做法是在header文件中声明一个object(或函数),并在一个源文件中定义它。例如,给定一个名为 foo
的 object 在名为 bar.c
的文件中定义为 MyType foo = 0;
,header 文件 bar.h
将声明 MyType foo;
.然后每个需要 foo
的源文件将使用 #include "bar.h"
来获取它的声明。
您所询问的代码的作者显然决定将定义和声明放在一起。他们的 header 文件 intdspmng.h
(根据包含防护的名称推测)可以包含在源文件中,并且通常会声明标识符。但是,当他们将其包含在 main.c
或他们指定为主文件的任何内容中时,他们首先定义 _MAIN_
,可能使用 #define _MAIN_
或 #define _MAIN_ 1
。然后,当它们包含 intdspmng.h
时,它会定义标识符而不是仅仅声明它们。
换句话说,那个人可能想“我想把这些东西的声明和定义放在一起,因为这样更容易编辑它们,也更容易看到定义和声明之间的关联。因此,我将编写可以放入 header 文件但仅定义主文件中内容的代码。”
这可能并非完全不合理。然而,他们犯了一个错误。声明的一个目的是检查它们是否与定义相匹配。如果在定义标识符的源文件中,我们还包括声明它们的 header,那么编译器会同时看到声明和定义,如果它们发生冲突,它将报告警告或错误,就像印刷发生错误或类型在一个地方更改,但在另一个地方没有更改。
这可以通过始终包含声明来补救,而仅当 _MAIN_
的定义要求时才包含定义:
extern dspList_t *gDspmngTab;
extern int nb_config_dspmng;
extern PARAM_COM_WEBSRV ParamCom;
#ifdef _MAIN_
dspList_t *gDspmngTab = NULL;
int nb_config_dspmng = 0;
PARAM_COM_WEBSRV ParamCom;
#endif
虽然这弥补了这个不足,但我仍然不会说我推荐这种方法。
另一个问题是,根据 C 标准,以下划线开头后跟大写字母或另一个下划线的标识符是保留的。在一般程序代码中应避免使用它们,尽管编译器和“系统”库可能会使用它们。所以_MAIN_
应该改成别的,比如DefineMainObjects
.