我正在尝试为多个嵌入式平台维护带有示例的代码库。我需要支持一些函数参数的“far”(非16位)指针的概念。
我认为我有一个很好的解决方案,在某些平台上将宏FAR
定义为__far
,在32位指针(嵌入式Linux,Win32等)的平台上没有任何内容。使用该宏,我可以轻松地将指针定义为somestruct_t FAR *foo
。
但后来我开始使用飞思卡尔处理器,他们的编译器要求FAR
在星号和变量名之间。 (somestruct_t * __far foo
)。
我提出的处理此案例的最佳解决方案是将宏FARPTR
定义为__far *
,* __far
或仅*
,具体取决于平台。这允许somestruct_t FARPTR foo
。
那里有更清洁的解决方案吗? 特别是,我不认为读取该代码的人看不到*
。我也担心在涉及函数声明时会遇到问题。从Freescale编译器帮助中获取此语法的负载:
int __far *f(); // __far function returning a pointer to int
int * __far f(); // Function returning a __far pointer to int
int __near * __far f(); // __near function returning a __far pointer to int
最后一个杀了我 - 返回类型中的内部表示近函数?!我最近了解到添加__near
还不足以将函数实际编译到近内存 - 我需要将它包装在pragma中。
那么,有没有人看到比我的FARPTR
宏观想法更好的解决方案?
答案 0 :(得分:2)
freescale处理器的使用与标准类型限定符(例如const
)更加一致,该放置使得它引用指针而不是指向的数据。也就是说,因为“远数据”而不是“远指针”将毫无意义,你会认为这无关紧要,但可能更大的一致性一个更简单的编译器解析器。
你可以使用像kludgey这样的东西:
#if defined __SOME_ARCHITECTURE__
#define DECLARE_FARPTR( type, identifier ) type __far * identifier
#if defined __SOME_OTHER_ARRCHITECTURE__
#define DECLARE_FARPTR( type, identifier ) type * __far identifier
#else
#define DECLARE_FARPTR( type, identifier )
#endif
然后您的声明如下:
DECLARE_FARPTR( somestruct_t, foo ) ;
或在函数原型中获取指针参数:
void fn( DECLARE_FARPTR( somestruct_t, foo ) ) ;
或返回远指针的函数:
DECLARE_FARPTR( somestruct_t, fn( void ) ) ;
正如您所看到的那样,它很快就会变得难以阅读,并且声明性函数式宏通常是最好避免的。
答案 1 :(得分:2)
我没有针对您的具体更好的解决方案。但是,我多次处理同样的问题,建议您对AUTOSAR Specification of Compiler Abstraction (PDF)进行审核。
它包括处理多个编译器的详细方法。
答案 2 :(得分:1)
要添加到Clifford's post,虽然类似函数的宏可能不是一个好主意,但您可以使用宏来创建typedef:
#ifdef SOME_ARCH
#define DEF_FAR_PTR(type, farptr_typename) typedef type __far *farptr_typename;
#elsif SOME_OTHER_ARCH
#define DEF_FAR_PTR(type, farptr_typename) typedef type * __far farptr_typename;
#else
#define DEF_FAR_PTR(type, farptr_typename) typedef type * farptr_typename;
#endif
答案 3 :(得分:1)
我也与飞思卡尔合作,我自己的解决方案是以下任一项:
1)尽可能用简单整数替换远指针。这在每种情况下都不起作用,但在处理函数指针时尤其有用,例如在编写中断向量表时。
2)不要使用远指针,而是将相同的代码写入编译器在远指针访问期间将产生的代码。以下是飞思卡尔MCU的示例:
unsigned char readFromPage (unsigned char page, const unsigned char* address)
{
unsigned char value;
unsigned char tmp = PPAGE;
SAFE_DisableInterrupts;
PPAGE = page;
value = *address;
PPAGE = tmp;
SAFE_EnableInterrupts;
return value;
}
(根据具体情况,可以内联此代码)
3)尽可能使用#pragmas。
因此,我的代码中没有单个远或近指针,它是可移植的(与硬件相关的代码可移植),我可以使用只了解标准C的静态分析器来检查它。
答案 4 :(得分:0)
定义两个FAR宏可能更简洁:一个用于*之前,另一个用于*之后。