在工作中遇到这样的一个问题:假设有1000个串口的数据需要接收并处理(串口的个数极端一些,目的是好说明问题),以Windows下的VC为例,一般的每一个串口接收都对应一个接收并处理函数,是不是需要写1000个这样的函数?这是第一个问题。如果每一个串口的接收处理函数都基本相同,唯一不同可以从传递进来的参数,在做接收处理时用该参数区分开来,那么是否可以将这1000个函数写成一个“共用”函数?这是第二个问题。
首先结论是,若1000个函数体内容大致都相同,是可以提取成一个共用函数,让1000个串口接收线程去勾连这个共用函数就可以了。
下面直接看仿真程序(VS2008控制台)和结论,判据是启动的每一个线程里,只要看到局部变量有自己的地址空间即OK!
// TestCmd.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "TestCmd.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// 唯一的应用程序对象
CWinApp theApp;
using namespace std;
typedef struct
{
char str[100];
int t;
}MY_PARAM;
MY_PARAM param[3]; //最好为全局,否则若定义在主线程中,退出去,该变量从栈中退出!!
//n个具体函数的定义及实现
UINT fn_helper( LPVOID pParam );
UINT fn1( LPVOID pParam );
UINT fn2( LPVOID pParam );
UINT fn3( LPVOID pParam );
//...........
//...........
//
// 函数指针数据定义, 和上面的函数类型、参数一一对应
//
typedef UINT (*ARRAY_FUNC[])(LPVOID pParam);
//第一种变量方式定义
ARRAY_FUNC af={fn1, fn2, fn3,};
//或者第二种变量方式定义
//af[0] = fn1;
//af[1] = fn2;
//.......
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// 初始化 MFC 并在失败时显示错误
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: 更改错误代码以符合您的需要
_tprintf(_T("错误: MFC 初始化失败\n"));
nRetCode = 1;
}
else
{
//1. 向全局变量中赋点数据
param[0].t=600; //传递到线程内,用于延时600ms打印
strcpy(param[0].str, "In func1");
param[1].t=800; //传递到线程内,用于延时800ms打印
strcpy(param[1].str, "In func2");
param[2].t=1000; //传递到线程内,用于延时1000ms打印
strcpy(param[2].str, "In func3");
printf("man: %08x, %08x, %08x\r\n", ¶m[0], ¶m[1], ¶m[2]);
//2. 线程启动
for(int i=0; i<sizeof(af)/sizeof(af[0]); i++)
{
//AfxBeginThread(af[i], ¶m[i]); //每一个单独处理
AfxBeginThread(fn_helper, ¶m[i]); //挂接共用函数
}
while(1)
{
}
}
return nRetCode;
}
UINT fn1( LPVOID pParam )
{
fn_helper(pParam);
return 0L;
}
UINT fn2( LPVOID pParam )
{
fn_helper(pParam);
return 0L;
}
UINT fn3( LPVOID pParam )
{
fn_helper(pParam);
return 0L;
}
UINT fn_helper( LPVOID pParam)
{
int localTmp=2000;
MY_PARAM *pMyParam = (MY_PARAM *)pParam;
printf("%08x, %s: %d, 局部变量地址=%08x\r\n",
pMyParam, pMyParam->str, pMyParam->t, &localTmp);
while(1)
{
Sleep(pMyParam->t);
printf("%08x, %s: %d, 局部变量地址=%08x\r\n",
pMyParam, pMyParam->str, pMyParam->t, &localTmp);
}
return 0L;
}
总结:通过对该问题的思考和解决,深刻理解了函数内有自己的栈地址空间这句话(与宏定义函数相比),以及函数指针数组的定义与用法。