我目前正在开发一个实现多个C源文件的程序。这是我第一个这样做的项目,并且有很多问题。对所有最近的问题感到抱歉,但我非常感谢你的帮助!
我有一个带有main函数的主源文件。在这个主要功能中,我有一个操作循环,可以调用高级'本质上是子程序的函数。例如,我有一个名为ReadInputs()的函数,它位于' ReadInputs.c'中。我严格按照这种方式将其分解为组织目的。
我有几个问题:
我听说最好将头文件与每个源文件相关联。因此,我可以将文件标题为' ReadInputs.h'其中包含在ReadInputs.c'中找到的ReadInputs()函数的原型。我的第一个问题是,有必要有这么简单的小头文件吗?截至目前,' ReadInputs.h'只包含一个原型。是否可以将此原型包含在整个头文件中?就我而言,我有一个标题为' Definitions.h'的整体标题文件。其中包括原型ReadInputs。
问题2:因为我想在每个源文件之间共享变量,所以我使用以下方法:
我在' main.c'中声明了一个变量。叫Var。在' Definitions.h'头文件,我extern Var。在每个其他源文件中,我#include Definitions.h。我相信这将允许变量在全球范围内共享。这是正确的假设吗?
对不起文字墙。任何帮助表示赞赏!
答案 0 :(得分:0)
对于你的第一个问题,是的,这经常发生。
例如,考虑一组实现平衡树的文件,使用不同的C源文件进行插入,删除查找等。这通常是为了更好的构建过程,例如只有重新编译insert
文件,如果这是你唯一的改变。
但是,您希望代码的用户只需要包含一个btree.h
,这样您就可以将所有函数原型(以及其他内容)整合到那里。
所以你最终会得到类似的东西:
btree.h - public stuff
btree_priv.h - private stuff
btreeInsert.c - individual functions
btreeDelete.c
btreeFind.c
btreeRebalance.c
btreeIterate.c
btree_priv.h
文件包含足够的信息,超出用户标题btree.h
,以允许自己的源文件中的各个函数了解彼此和"隐藏&# 34;数据结构。
然后,您通常会打包所有已编译的"个别函数"将对象文件放入库中,然后分发库和公共头文件。
对于第二个问题也是如此,但有一点需要注意。 extern
将显式声明变量,以便其他翻译单元(源文件)知道它。但它是(例如)在文件级别将其声明为非静态的行为,以便在链接时将其显示为您链接的所有文件。
答案 1 :(得分:0)
原型,结构等应该在头文件中。它是一个很好的实践和行业遵循这一规则。随着你的代码库增加,你将添加不同的函数,你的头文件也会增长,所以你不必担心。
是的,你是对的。
答案 2 :(得分:0)
three files are included below
first the top level makefile
then the bottom level makefile
then an example source file
Note: the makefiles are using 'sed' for
the creation of the dependency files
however, the gcc compiler has
appropriate parameters that
can make the operation much simplier
in general, the way to use this is:
-- in the top level directory
make -f makefile -dDEBUG > make.out
then examine the file make.out to search for any compile/link errors
Note: I do not know why some lines are being displayed in large/bold font
--- file: makefile.mak
SHELL = /bin/sh
# note: this makefile.mak needs to be run from the ./src directory
# of the GOT4 directory tree
SRC := $(wildcard *.c)
OBJ := $(SRC:.c=.o)
DEP := $(SRC:.c=.d)
INC := $(SRC:.c=.h)
MAKE := /usr/bin/make
CC := /usr/bin/gcc
CP := cp
MV := mv
LDFLAGS := -L/usr/local/lib -L/usr/lib -L/lib
DEBUG := -ggdb3
CCFLAGS := $(DEBUG) -Wall -W
#CPPFLAGS += =MD
LIBS := -lssl -ldl -lrt -lz -lc -lm
.PHONY: AllDirectories
# the following statement needs to be edited as
# subdirectories are added/deleted/re-named
#AllDirectories := \
# Command_Configuration \
# Communication \
# Main_Scheduler \
# Retrieve_CDS_Log \
# Retrieve_EventRecorder_Log \
# Retrieve_GPS \
# Retrieve_QES_Alarm_Log \
# Retrieve_QES_RealTime \
# Write_CDS_Log
AllDirectories := \
Main_Scheduler \
Communication \
Retrieve_GPS \
Test_Communication_Dev
.PHONY: all
#all: $(OBJ) $(AllDirectories)
# $(foreach d,$(AllDirectories), \
# ( cd $d && $(MAKE) -f makefile.mak name=Tsk_$d all ); )
all: $(OBJ) $(AllDirectories)
$(foreach d,$(AllDirectories), \
( cd $d && $(MAKE) -f ../makefile.bot name=Tsk_$d all ); )
#
# create dependancy files
#
%.d: %.c
#
# ========= START $< TO $@ =========
$(CC) -M $(CPPFLAGS) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
# ========= END $< TO $@ =========
#
# compile the .c file into .o files using the compiler flags
#
%.o: %.c %.d
#
# ========= START $< TO $@ =========
$(CC) $(CCFLAGS) -c $< -o $@ -I.
# ========= END $< TO $@ =========
#
.PHONY: clean
#clean: $(AllDirectories)
# # ========== start clean activities ==========
# rm -f *.o
# rm -f $(name).map
# rm -f $(name)
# rm -f *.d
# $(foreach d,$(AllDirectories), \
# ( cd $d && $(MAKE) -f makefile.mak clean ); )
# # ========== end clean activities ==========
clean: $(AllDirectories)
# ========== start clean activities ==========
rm -f *.o
rm -f $(name).map
rm -f $(name)
rm -f *.d
rm -f ../bin/Tsk_*
$(foreach d,$(AllDirectories), \
( cd $d && $(MAKE) -f ../makefile.bot name=Tsk_$d clean ); )
# ========== end clean activities ==========
.PHONY: install
#install: $(AllDirectories)
# # ========== start install activities ==========
# $(foreach d,$(AllDirectories), \
# ( cd $d && $(MAKE) -f makefile.mak clean ); )
# # ========== end install activities ==========
install: $(AllDirectories)
# ========== start install activities ==========
$(foreach d,$(AllDirectories), \
( cd $d && $(MAKE) -f ../makefile.bot name=Tsk_$d install ); )
# ========== end install activities ==========
# include the contents of all the .d files
# note: the .d files contain:
# <filename>.o:<filename>.c plus all the dependancies for that file
# I.E. the #include'd header files
# wrap with ifneg... so will not rebuild *.d files when goal is 'clean'
#
ifneq "$(MAKECMDGOALS)" "clean"
-include $(DEP)
endif
then the makefile (located in the top level directory)
that creates each of the sub directory executables
-- file: makefile.bot
SHELL = /bin/sh
BINDIR := /home/user/bin
.PHONY: all
all : $(BINDIR)/$(name) ../makefile.mak ../makefile.bot
#
# macro of all *.c files
# (NOTE:
# (the following 'wildcard' will pick up ALL .c files
# (like FileHeader.c and FunctionHeader.c
# (which should not be part of the build
# (so be sure no unwanted .c files in directory
# (or change the extension
#
SRC := $(wildcard *.c)
OBJ := $(SRC:.c=.o)
DEP := $(SRC:.c=.d)
INC := $(SRC:.c=.h)
COMMON_OBJ := $(wildcard ../*.o)
#COMMON_SRC := $(wildcard ../*.c)
#COMMON_OBJ := $(COMMON_SRC:.c=.o)
#COMMON_DEP := $(COMMON_SRC:.c=.d)
#COMMON_INC := $(COMMON_SRC:.c=.h)
MAKE := /usr/bin/make
CC := /usr/bin/gcc
CP := cp
MV := mv
LDFLAGS := -L/usr/local/lib
DEBUG := -ggdb3
CCFLAGS := $(DEBUG) -Wall -W
#CPPFLAGS += =MD
#LIBS := -lidn -lssl -ldl -lrt -lz -lc -lm
LIBS := -lssl -ldl -lrt -lz -lc -lm
#
# link the .o files into the executable
# using the linker flags
# -- explicit rule
#
$(name): $(OBJ) $(COMMON_OBJ) ../makefile.mak ../makefile.bot
#
# ======= $(name) Link Start =========
$(CC) $(LDFLAGS) -o $@ $(OBJ) $(COMMON_OBJ) $(LIBS)
# ======= $(name) Link Done ==========
#
# note:
# using MV rather than CP results in all executables being re-made everytime
$(BINDIR)/$(name): $(name)
#
# ======= $(name) Copy Start =========
sudo $(CP) $(name) $(BINDIR)/.
# ======= $(name) Copy Done ==========
#
#
#create dependancy files -- inference rule
# list makefile.mak as dependancy so changing makfile forces rebuild
#
%.d: %.c
#
# ========= START $< TO $@ =========
$(CC) -M $(CPPFLAGS) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
# ========= END $< TO $@ =========
#
# compile the .c file into .o files using the compiler flags
# -- inference rule
#
%.o: %.c %.d
#
# ========= START $< TO $@ =========
$(CC) $(CCFLAGS) -c $< -o $@ -I.
# ========= END $< TO $@ =========
#
.PHONY: clean
clean:
# ========== CLEANING UP ==========
rm -f *.o
rm -f $(name).map
rm -f $(name)
rm -f *.d
# ========== DONE ==========
.PHONY: install
install: all
# include the contents of all the .d files
# note: the .d files contain:
# <filename>.o:<filename>.c plus all the dependancies for that .c file
# I.E. the #include'd header files
# wrap with ifneg... so will not rebuild *.d files when goal is 'clean'
#
ifneq "$(MAKECMDGOALS)" "clean"
-include $(DEP)
endif
and finally, a typical file, showing the many local and system headers used
note: although the usage was trivial in this file,
the doxygen documentation utility
was used in the process of automatic document creation
-- file: Main_Scheduler.c
/**
@file Main_Scheduler.c
@brief contains functions to control 'deleted'
@author Richard Williams
@date June 27, 2012
*/
/* SIRT issues applied to this file:
SIRT issue ### -
*/
/* *************** Included files ************************************* */
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h> // for system() and itoa() utilities
#include <stdarg.h> // for va_list(), etc
#include <string.h> // string handling utilities
#include <semaphore.h> // semaphores handling utilities
#include <fcntl.h> // symbolic definitions for flags bits
#include <sys/types.h> // contains definitions of data types used in system calls
#include <sys/socket.h>// type definitions (I.E. struct sockaddr_in)
#include <sys/stat.h> // symbolic definitions for permission bits and open()
#include <sys/ipc.h> // ipc interface utilities
#include <sys/shm.h> // shared memory utilities
#include <arpa/inet.h> // defines INADDR_ANY, etc
#include <errno.h> // for accessing errno and related functions
#include <stdbool.h> // define true, false, bool
#include <time.h> // prototypes for time() and related functions
// contains common data type definitions
#include "../GOT4_Types.h"
// contains data definitions for ON and OFF
#include "../CdsDefines.h"
// contains prototypes for Interprocess Communication
#include "../Common_Interprocess_Communication.h"
// contains prototypes for UDP utility functions
#include "../Common_UDP_Utilities.h"
// contains prototypes and enums for configuration operations
#include "../CommonConfiguration.h"
// contains prototypes for writing to CDS Log file
#include "../CommonWriteCdsLog.h"
// contains prototypes for handling stderr files
#include "../CommonDateFunctions.h"
// contains prototypes and enums for watchdog operations
#include "Main_Scheduler_Watchdog.h"
// contains prototypes and enums for command operations
#include "Main_Scheduler_Command.h"
//contains prototypes for globally visible functions and data types in this file
#include "Main_Scheduler.h"
/* *************** File static functions ****************************** */
static enum enumReturnStatus Main_Scheduler_StartTask( INT32 taskSelector );
static enum enumReturnStatus Main_Scheduler_StopTask ( INT32 taskSelector );
static enum enumReturnStatus Main_Scheduler_Task__Initialize( void );
static enum enumReturnStatus Main_Scheduler_Config__Initialize( BOOL bFirstTime );
#define dMAX_IPC_PAYLOAD ( 256 )
#define dMAX_SYSTEM_BUF_LENGTH ( 256 )
/* *************** Global Variables *********************************** */
/* *************** File Static Variables ****************************** */
static BOOL ActiveTaskTable[ eMaxTasks ] = { FALSE };
// used to format the payload of messages to write to IPC
//static char inITC_payload[ dMAX_IPC_PAYLOAD ];
static char outITC_payload[ dMAX_IPC_PAYLOAD ];
// used for executing commands in shell
static char systemCommand[dMAX_SYSTEM_BUF_LENGTH] = {0x00};
// used to enable kicking the hardware watchdog
static BOOL flgWatchdogKick = TRUE;
/* *************** Code *********************************************** */
/**
@fn INT32 main(INT32 argc, char *argv[])
@brief -
@param [in] argc -
@param [in] argv -
@return INT32 -
:
*/
INT32 main( INT32 argc __attribute__ ((unused)), char* argv[] )
{
enum enumReturnStatus returnStatus;
INT32 taskSelector; // loop counter
INT32 CommandValue; // command to send to sub task
struct structWriteIPC WriteIPC;
struct timespec timeout; // timeout for interprocess communication call
unsigned priority; // message priority for sending messages, 5 is low, 10 is high
char *pBaseName = gnu_basename( argv[ 0 ]); // get name of this file
remove_all_IPC(); // Only done from Main Scheduler, clears out all external (OS) interprocess buffers
Initialize_IPC();
itc_payload_size_init();
set_TaskSelector( eTask_Main_Scheduler );
set_pTask_NameString( eTask_Main_Scheduler, pBaseName );
// select initial file to receive stderr messages
CommonDateFunctions_stderr( pBaseName );
// initialize the logging subsystem, indicating not owner of resource
CommonWriteCdsLog__Initialize();
if( atexit( release_CommonConfiguration ) )
{ // then setting exit function failed
CommonWriteCdsLog( eLL_Critical,
get_pFormatString( eFormat_CFFL_string_string ),
__FILE__, __LINE__,
"LibFunc:atexit()",
strerror(errno) );
system( "sync; sync;" );
exit( EXIT_FAILURE);
}
/*
* ***************************************************************
* implied else (atexit() successful)
*****************************************************************
*/
// read .config file and initialize database
Main_Scheduler_Config__Initialize( TRUE ); // true=first time
returnStatus = Main_Scheduler_Task__Initialize();
// pass tracking message to CDS log file
CommonWriteCdsLog( eLL_Info,
get_pFormatString( eFormat_IFFL_string ),
__FILE__, __LINE__,
"Entering main execution loop" );
/*
*********************************************************************
* main operating loop starts here
* *******************************************************************
*/
flgWatchdogKick = true;
while( flgWatchdogKick )
{
// step to next stderr file at midnight, otherwise do nothing
CommonDateFunctions_stderr( pBaseName );
// 11 kick the CPU watchdog
Main_Scheduler_wd_kick();
// 12) kick the external watchdog
//todo:
for( taskSelector=1; // step by main_scheduler task=(0)
taskSelector<eMaxTasks ;
taskSelector++ )
{
if( !ActiveTaskTable[ taskSelector ] )
{ // then selected task not configured to run
continue; // step to next itteration of inner loop
}
/*
*********************************************************************
* implied else, task-of-interest ready to run
* *******************************************************************
*/
// throttle execution rate of sub tasks
step_Interval_counter( taskSelector );
if( is_Interval_expired( taskSelector) )
{ // then, kick related task
reset_Interval_counter( taskSelector );
// note: get_Task_command() handles all errors
CommandValue = get_Task_command( taskSelector );
if( eTask_Retrieve_GPS == taskSelector )
{
CommandValue = eTaskCommand_GetGPSreport; // periodic event
}
fprintf( stdout,"DEBUG:File:%s\n\t--> ATTEMPTING TO KICK cmd#:%d TASK# %d\n", __FILE__, CommandValue, taskSelector );
fflush( stdout );
fprintf( stdout,"DEBUG:File:%s\n\t--> task:%d, command;%d\n\n", __FILE__, taskSelector, CommandValue );
fflush( stdout );
memset( outITC_payload, 0x00, sizeof(outITC_payload) );
((struct structITC_Command*)outITC_payload)->ITC_Receiver = taskSelector;
((struct structITC_Command*)outITC_payload)->ITC_Command = CommandValue;
WriteIPC.TaskSelector = taskSelector;
WriteIPC.ITC_MsgType = eITC_MsgType_Command;
WriteIPC.ITC_PayLoadSize = 2*sizeof(INT32);
WriteIPC.pITC_Payload = outITC_payload;
fprintf( stdout,"DEBUG:File:%s\n\t--> calling write_ITC_Record_To_IPC() with taskSelector:%d\n\n", __FILE__, taskSelector );
fflush( stdout );
clock_gettime(CLOCK_REALTIME, &timeout); // gets current time
timeout.tv_sec += 1; // adds one second to current time for timeout
priority = 10;
returnStatus = write_ITC_Record_To_IPC( &WriteIPC, &timeout, priority );
fprintf( stdout,"DEBUG:File:%s\n\t--> returned from write_ITC_Record_To_IPC()\n\n", __FILE__ );
fflush( stdout );
if( eRS_Success == returnStatus )
{ // then. write successful
fprintf( stdout,"DEBUG:File:%s\n\t--> SUCCESFULLY SENT MSG TO TASK#%d\n", __FILE__, taskSelector );
fflush( stdout );
// overwrite command so not executed again.
set_Task_command( taskSelector, eTaskCommand_DoNothing );
}
else
{
fprintf( stdout,"DEBUG:File:%s\n\t--> FAILED TO SEND MSG TO TASK#%d error is:%d\n", __FILE__, taskSelector, returnStatus );
fflush( stdout );
}
} // endif( is interval expired )
} // end for( each task )
// wait a second before going through the above again
sleep(1);
// 16) get any new commands
// rkw: comment until ready to receive commands from CommandConfiguration task
// Main_Scheduler_Command();
} // end while( flgWatchdogKick )
CommonWriteCdsLog( eLL_Info,
get_pFormatString( eFormat_IFFL_Exiting_Status ),
__func__, __FILE__, EXIT_SUCCESS );
return( EXIT_SUCCESS );
} // end main()
static enum enumReturnStatus Main_Scheduler_StartTask( INT32 taskSelector )
{
char *pTask_NameString;
int systemReturn;
if( is_taskSelector_Valid( taskSelector) )
{
// note: task_nameString is setup during call to Main_Scheduler_Config__Initialize()
pTask_NameString = get_pTask_NameString( taskSelector );
if( NULL != pTask_NameString )
{ // then get_pTask_NameString successful
memset( systemCommand, 0x00, sizeof(systemCommand) );
// set the command string
// set to run in background so will get execution back
sprintf( systemCommand, "%sTsk_%s &", dEXECUTION_DIR, pTask_NameString );
// pass tracking message to CDS log file
CommonWriteCdsLog( eLL_Critical, // Critical to assure will be written to log file
get_pFormatString( eFormat_CFFL_string ),
__FILE__, __LINE__,
systemCommand );
fprintf( stdout,"DEBUG:File:%s\n\t--> starting subsytem: %s\n", __FILE__, systemCommand );
fflush( stdout );
// run the command ( which starts the task )
systemReturn = system( systemCommand );
if (( 0 != systemReturn ) )
{
CommonWriteCdsLog( eLL_Critical,
get_pFormatString( eFormat_CFFL_digit_string ),
__FILE__, __LINE__, systemReturn,
"system() call failed." );
system( "killall Tsk*" );
system("sync;sync;");
exit( EXIT_FAILURE );
}
return( eRS_Success ); // indicate operation successful
}
//else
//{ // else, get_pTask_NameString() failed
// which means the task is not configured in the .config file
// CommonWriteCdsLog( eLL_Error,
// get_pFormatString( eFormat_EFFL_digit_string ),
// __FILE__, __LINE__,
// taskSelector,
// "=taskSelector: Function:get_pTask_NameString() failed" );
//} // endif( got task name string )
}
else
{ // else, bad parameter
CommonWriteCdsLog( eLL_Error,
get_pFormatString( eFormat_EFFL_digit_string ),
__FILE__, __LINE__,
taskSelector,
"=taskSelector: Parameter out of range" );
}
return( eRS_Failure ); // indicate error occurred
} // end Main_Scheduler_StartTask()
static enum enumReturnStatus Main_Scheduler_StopTask ( INT32 taskSelector )
{
char systemCommand[ 256 ];
char *pTask_NameString;
if( is_taskSelector_Valid( taskSelector ) )
{
memset( systemCommand, 0x00, sizeof(systemCommand) );
pTask_NameString = get_pTask_NameString( taskSelector );
if( NULL != pTask_NameString )
{ // then, get_pTask_NameString successful
sprintf( systemCommand, "killall %sTsk_%s", dEXECUTION_DIR, pTask_NameString );
// pass tracking message to CDS log file
CommonWriteCdsLog( eLL_Critical,
get_pFormatString( eFormat_CFFL_string ),
__FILE__, __LINE__,
systemCommand );
// run the command, which kills the task
system( systemCommand );
return( eRS_Success ); // indicate success
}
}
else
{ // else, bad parameter
CommonWriteCdsLog( eLL_Error,
get_pFormatString( eFormat_EFFL_digit_string ),
__FILE__, __LINE__,
taskSelector,
"=taskSelector: Parameter out of range" );
}
return( eRS_Failure ); // indicate problem occurred
} // end Main_Scheduler_StopTask()
static enum enumReturnStatus Main_Scheduler_Config__Initialize( BOOL bFirstTime )
{
enum enumReturnStatus returnStatus = eRS_Success;
// Note: check for first time avoids trying to 'free() un-initialized char pointers
if( !bFirstTime )
{
release_CommonConfiguration();
}
clear_CommonConfiguration();
acquire_CommonConfiguration( eDivision_Main_Scheduler );
return( returnStatus );
} // end Main_Scheduler_Config__Initialize()
static enum enumReturnStatus Main_Scheduler_Task__Initialize( void )
{
enum enumReturnStatus returnStatus = eRS_Success;
INT32 taskSelector;
// 2) reset the IOC card
memset( systemCommand, 0x00, sizeof(systemCommand) );
strcat( systemCommand, "/usr/bin/diag_client -s 172.20.100.17:23 'reset'" );
//rkw for testing system( systemCommand );
// 3) reset the DIO card
memset( systemCommand, 0x00, sizeof(systemCommand) );
strcat( systemCommand, "/usr/bin/diag_client -s 172.20.100.18:23 'reset'" );
//rkw for testing system( systemCommand );
/*
*********************************************************************
* start task execution
* *******************************************************************
*/
// pass tracking message to CDS log file
CommonWriteCdsLog( eLL_Info,
get_pFormatString( eFormat_IFFL_string ),
__FILE__, __LINE__,
"kill any running Task" );
for( taskSelector=1; // task 0 is Main_Scheduler (I.E. this task)
eMaxTasks > taskSelector;
taskSelector++ )
{
Main_Scheduler_StopTask( taskSelector );
}
// pass tracking message to CDS log file
CommonWriteCdsLog( eLL_Info,
get_pFormatString( eFormat_IFFL_string ),
__FILE__, __LINE__,
"Entered: Start Task Execution Loop" );
for( taskSelector=1; // task 0 is Main_Scheduler (I.E. this task)
eMaxTasks > taskSelector;
taskSelector++ )
{
returnStatus = Main_Scheduler_StartTask( taskSelector );
if( eRS_Success == returnStatus )
{
ActiveTaskTable[ taskSelector ] = TRUE;
}
else
{ // else, task not configured
ActiveTaskTable[ taskSelector ] = FALSE;
}
} // end for( each possible task )
/*
*********************************************************************
* initialization loop
* *******************************************************************
*/
// 8) set task initializer command for each task
for( taskSelector=1; // step by Main_Scheduler task=0
taskSelector>=eMaxTasks;
taskSelector++ );
{
set_Task_command( taskSelector, eTaskCommand_Initialize );
} // end for( each task to initialize )
/*
*********************************************************************
* initialze CPU card and external watchdog operations
* *******************************************************************
*/
// 9) initialize the CPU watchdog
Main_Scheduler_wd_init();
Main_Scheduler_wd_enable();
// 9.1 set kickWatchdog flag to indicate watchdog is to be kicked
flgWatchdogKick = TRUE;
// 10) initialize throttle timers
// pass tracking message to CDS log file
CommonWriteCdsLog( eLL_Info,
get_pFormatString( eFormat_IFFL_string ),
__FILE__, __LINE__,
"resetting all timers" );
for( taskSelector=0;
taskSelector<eMaxTasks ;
taskSelector++ )
{
reset_Interval_counter( taskSelector );
}
return( returnStatus );
} // end Main_Scheduler_Task__Initialize()
/* ******************************************************************** **
** End of source file: Main_Scheduler.c
** ******************************************************************** */
I know the above examples contain the information that you need
for your project.
But it may be a bit difficult to decyper without knowing
the makefile syntax and builtin calls
答案 3 :(得分:0)
是的,最好为每个源文件使用单独的头文件/ .inc文件。业界遵循规则要么为每个.c文件都有.h文件或.inc文件。函数原型,枚举,宏,结构等应在.h或.inc文件中声明。
是的,您使用全局变量的方式是正确的。 始终在.c文件中声明全局变量,避免在任何.h文件中声明全局变量,因为在某些编译器中它可能导致多个定义错误。