我是C语言的初学者,我有一个关于编译C文件的问题。我需要为带有main()的应用程序编写一个通用包代码(common.c),以解析配置文件并设置一些变量。我需要将此文件导入另一个文件,例如使用 #include(?) 的 local.c,并再次在此处使用 main() 并在 common.c 中调用某些函数。现在,当我使用 gcc 编译这些文件时,我收到一个错误:main() 的多个声明。
有没有办法先编译和运行common.c,然后在local.c中使用此文件设置的变量?我应该使用哪些生成文件规则?
普通.h
#ifndef __DAEMON_COMMON__
#define __DAEMON_COMMON__
extern int a;
extern const char* type;
int add(int a, int b);
void print(int n);
#endif
通用.c
int a = -1;
int main(int argc, char *argv[]){
// parse file in arg and initialize variables declared as extern
a = 10;
}
int add(int a, int b){
return a + b;
}
void print(int n){
printf("%d",n);
}
common.c 和 common.h 位于 common.c 中,
使用#include <common.h>
本地.c
#include <common.h>
int main(){
add(5,10);
print(a); // I want to access 'a' initialized in common.c here
return 0;
}
如注释中所述和编译器报告的那样,您不能有多个main
函数。您必须从编译中排除除单个main
函数之外的所有函数,或者重命名其他函数并自行调用它(它们)。
common.c
中main
函数的目的似乎是变量的初始化。您可以通过不同的方式执行此操作。
使用问题中的示例,您可以简单地执行正确的静态初始化,而无需使用函数。
普通.h
#ifndef __DAEMON_COMMON__
#define __DAEMON_COMMON__
extern int a;
extern const char* type;
int add(int a, int b);
void print(int n);
#endif
通用.c
/* add this include here to allow the compiler to check your implementation against the declaration */
#include "common.h"
/* correct initialization here instead of a main() function */
int a = 10;
int add(int a, int b){
return a + b;
}
void print(int n){
printf("%d",n);
}
本地.c
/* #include <...> is normally used for system include files, #include "..." for files from your project */
#include "common.h"
int main(){
add(5,10); /* useless call because result is unused and no side effects in function */
print(a); // I want to access 'a' initialized in common.c here
return 0;
}
假设在您的实际用例中,所需的初始化更复杂,并且旨在依赖于命令行参数,则可以使用初始化函数以不同的方式解决此问题。
请注意,以下代码中使用OPTION1
或OPTION3
进行条件编译的不同选项用于在单个源代码中演示不同的解决方案。与其以这种方式实现它,不如简单地选择适合您的要求或最喜欢的选项。
普通.h
#ifndef __DAEMON_COMMON__
#define __DAEMON_COMMON__
extern int a;
extern const char* type;
int add(int a, int b);
void print(int n);
/* option 1: main() processes command line args and calculates value */
void common_init_a(int value);
/* option 2: main() passes command line args for processing in common.c */
void common_init(int argc, char **argv);
#endif
通用.c
#include "common.h"
int a = -1;
int add(int a, int b){
return a + b;
}
void print(int n){
printf("%d",n);
}
/* option 1 */
void common_init_a(int value) {
a = value;
}
/* option 2 */
void common_init(int argc, char **argv) {
/* process argc and argv to calculate the value for a */
a = 10; /* In reality this is a calculated value, not a constant */
}
本地.c
#include "common.h"
int main(int argc, char **argv){
/* run the initialization of the common module */
#ifdef OPTION1
/* option 1 */
/* process argc and argv to calculate the value for a */
common_init_a(10); /* In reality this is a calculated value, not a constant */
#else
/* option 2 */
common_init(argc, argv) {
#endif
add(5,10);
print(a); // I want to access 'a' initialized in common.c here
return 0;
}
此解决方案的缺点是初始化必须由使用common
模块的任何程序显式调用。
您可以通过多种方式改进这一点。您可以将"已初始化"状态保存在common.c
中,并使您的函数返回错误,以防之前未初始化。如果初始化不依赖于输入值,则函数可以在必要时隐式运行初始化。
通用.c
#include "common.h"
/* option 3, see below */
static void init_internal(void);
int a = -1;
static int initialized = 0;
int add(int a, int b){
if(!initialized) {
#ifndef OPTION3
/* option 1 or 2 */
/* handle error */
return ERROR_INDICATION; /* not very useful for this "add" function, but maybe in the real use case */
#else
/* option 3: implicit initialization as required */
init_internal();
#endif
}
return a + b;
}
void print(int n){
printf("%d",n);
}
/* option 1 */
void common_init_a(int value) {
a = value;
initialized = 1;
}
/* option 2 */
void common_init(int argc, char **argv) {
/* process argc and argv to calculate the value for a */
a = 10; /* In reality this is a calculated value, not a constant */
initialized = 1;
}
/* option 3: internal initialization without input values */
static void init_internal(void) {
a = 10;
initialized = 1;
}
本地.c
#include "common.h"
int main(int argc, char **argv){
/* With option 3, initialization is implicit in every function that requires it. */
#ifndef OPTION3
/* run the initialization of the common_module */
# ifdef OPTION1
/* option 1 */
/* process argc and argv to calculate the value for a */
common_init_a(10); /* In reality this is a calculated value, not a constant */
# else
/* option 2 */
common_init(argc, argv) {
# endif
#endif
add(5,10);
print(a); // I want to access 'a' initialized in common.c here
return 0;
}
编辑作为对评论的回复
这是嵌入式软件项目的一部分 [...]
common.c
中的main()
解析文件并初始化变量,在我的local.c
中,我有一个main()
,我在其中调用函数并使用在common.c
中声明和定义的变量common.h
您必须重命名其中一个函数。
与上面显示的解决方案不同,local.c
的函数main()
调用common_init()
或类似的函数,您可以从common.c
中调用函数,相反,并要求特定的(本地)应用程序代码具有名为local_main()
的函数(或由函数调用在common.c
中定义的任何名称)具有特定的签名和行为,该签名和行为将从common.c
中的main()
调用。
例:
普通.h
#ifndef __DAEMON_COMMON__
#define __DAEMON_COMMON__
extern int a;
extern const char* type;
int add(int a, int b);
void print(int n);
/* declaration of required function in local.c */
int local_main(void);
#endif
通用.c
#include "common.h"
int a = -1;
int main(int argc, char *argv[]){
// parse file in arg and initialize variables declared as extern
a = 10;
return local_main();
}
int add(int a, int b){
return a + b;
}
void print(int n){
printf("%d",n);
}
本地.c
#include "common.h"
int local_main(){
add(5,10);
print(a); // I want to access 'a' initialized in common.c here
return 0;
}