C 使用内联函数多次定义链接器错误

C 使用内联函数多次定义链接器错误,c,embedded,inline-code,multiple-definition-error,greenhills,C,Embedded,Inline Code,Multiple Definition Error,Greenhills,链接器正在报告内联函数的多定义错误 我在头文件中有以下代码: struct Port_Pin { volatile uint32_t * port_addr_set_value; //!< Writing the pin value here sets the pin to high. volatile uint32_t * port_addr_clr_value; //!< Writing the pin value to this po

链接器正在报告内联函数的多定义错误

我在头文件中有以下代码:

struct Port_Pin
{
    volatile uint32_t *     port_addr_set_value;    //!< Writing the pin value here sets the pin to high.
    volatile uint32_t *     port_addr_clr_value;    //!< Writing the pin value to this port clears the pin to low.
    volatile uint32_t *     port_addr_read_value;   //!< Address to read pin value.
    volatile uint32_t *     port_addr_enable;       //!< Writing the pin value here enables the pin (for reading or writing).
    volatile uint32_t *     port_addr_disable;      //!< Writing the pin value here disables the pin.
    volatile uint32_t *     port_addr_dir_output;   //!< Writing the pin value here sets the pin as an output.
    volatile uint32_t *     port_addr_dir_input;    //!< Writing the pin value here sets the pin as an input.
    unsigned int            pin_bit_position;       //!< Zero based, where position zero is first bit position.
};

inline void
Write_Port_Pin(const struct Port_Pin *  p_port,
               uint8_t                  bit)
{
    volatile uint32_t * port_addr = 0;
    port_addr = ((bit & 1) == 0) ? p_port->port_addr_clr_value
        : p_port->port_addr_set_value;
    *port_addr = 1 << p_port->pin_bit_position;
    return;
}
struct-Port\u-Pin
{
volatile uint32\u t*port\u addr\u set\u value;//!<在此处写入管脚值将管脚设置为高。
volatile uint32*port\u addr\u clr\u value;//!<将管脚值写入此端口会将管脚清除为低。
易失性uint32*port\u addr\u read\u value;//!<读取引脚值的地址。
volatile uint32*port\u addr\u enable;/!<在此处写入管脚值将启用管脚(用于读取或写入)。
volatile uint32*port\u addr\u disable;/!<在此处写入管脚值将禁用管脚。
volatile uint32*port\u addr\u dir\u output;//!<在此处写入管脚值将管脚设置为输出。
volatile uint32*port\u addr\u dir\u input;//!<在此处写入管脚值将管脚设置为输入。
无符号整数管脚位置;//!<基于零,其中位置零是第一位位置。
};
内联空隙
写入端口号(常量结构端口号*端口号),
uint8(t位)
{
易失性uint32\u t*端口地址=0;
端口地址=((位&1)==0)?p\U端口->端口地址clr\U值
:p_port->port_addr_set_value;
*端口地址=1引脚位位置;
返回;
}
我将头文件包括在多个源(.c)文件中

我希望将上述函数内联粘贴到调用它的任何位置。
在包含的每个源文件中没有函数的多个定义的情况下,是否有一种方法可以实现此目的?如果是,请提供示例

我需要对嵌入式平台进行性能优化。
编译器或链接器是否足够智能,可以在其他翻译单元中定义函数时内联函数?


我正在嵌入式ARM9平台上使用Green Hills编译器4.2.4。假设是2000年以前的C语言标准。这是C代码而不是C++。p> inline只是一个建议,而不是命令。然而,一般来说,编译器足够聪明,可以做正确的事情(而且Green Hills在优化方面有很好的声誉)

使函数“static inline”,这将阻止编译器使符号可导出。这将修复您的多个定义链接错误。。。链接器抱怨从多个源模块导出了相同的函数。

一些重要注意事项:

看来你没有很好地保护你的头球

#ifndef NAME_H
#define NAME_H
//...contents go here...
#endif // NAME_H
这可以防止标题多次为
#include
d时出现多个定义


您似乎还认为可以强制编译器内联函数。这是不对的。撇开一个疯狂而模糊的编译器标志不谈,编译器将始终决定是否要在生成的代码中内联您的函数。inline关键字的含义/用途与您所想的不同,请参见C中的无论函数是否为inline,您都不能在多个位置定义具有相同名称的函数

处理此问题的最佳方法是在标头中声明函数(以及它所依赖的结构定义,如下所示:

/* port_control.h */

struct Port_Pin              
{              
    volatile uint32_t *     port_addr_set_value;    //!< Writing the pin value here sets the pin to high.              
    volatile uint32_t *     port_addr_clr_value;    //!< Writing the pin value to this port clears the pin to low.              
    volatile uint32_t *     port_addr_read_value;   //!< Address to read pin value.              
    volatile uint32_t *     port_addr_enable;       //!< Writing the pin value here enables the pin (for reading or writing).              
    volatile uint32_t *     port_addr_disable;      //!< Writing the pin value here disables the pin.              
    volatile uint32_t *     port_addr_dir_output;   //!< Writing the pin value here sets the pin as an output.              
    volatile uint32_t *     port_addr_dir_input;    //!< Writing the pin value here sets the pin as an input.              
    unsigned int            pin_bit_position;       //!< Zero based, where position zero is first bit position.              
};              

/* Declare the function here so other modules know about it. */        
inline void              
Write_Port_Pin(const struct Port_Pin *  p_port,              
               uint8_t                  bit);
/*端口控制.h*/
结构端口号
{              
volatile uint32\u t*port\u addr\u set\u value;//!<在此处写入管脚值将管脚设置为高。
volatile uint32*port\u addr\u clr\u value;//!<将管脚值写入此端口会将管脚清除为低。
易失性uint32*port\u addr\u read\u value;//!<读取引脚值的地址。
volatile uint32*port\u addr\u enable;/!<在此处写入管脚值将启用管脚(用于读取或写入)。
volatile uint32*port\u addr\u disable;/!<在此处写入管脚值将禁用管脚。
volatile uint32*port\u addr\u dir\u output;//!<在此处写入管脚值将管脚设置为输出。
volatile uint32*port\u addr\u dir\u input;//!<在此处写入管脚值将管脚设置为输入。
无符号整数管脚位置;//!<基于零,其中位置零是第一位位置。
};              
/*在此处声明函数,以便其他模块了解它。*/
内联空隙
写入端口号(常量结构端口号*端口号),
uint8_t位);
然后在一个地方定义.c源文件中的函数:

/* port_control.c */

#include "port_control.h"

inline void                     
Write_Port_Pin(const struct Port_Pin *  p_port,                     
               uint8_t                  bit)                     
{                     
    volatile uint32_t * port_addr = 0;                     
    port_addr = ((bit & 1) == 0) ? p_port->port_addr_clr_value                     
        : p_port->port_addr_set_value;                     
    *port_addr = 1 << p_port->pin_bit_position;                     
    return;                     
} 
/*port\u control.c*/
#包括“port_control.h”
内联空隙
写入端口号(常量结构端口号*端口号),
uint8(t位)
{                     
易失性uint32\u t*端口地址=0;
端口地址=((位&1)==0)?p\U端口->端口地址clr\U值
:p_port->port_addr_set_value;
*端口地址=1引脚位位置;
返回;
} 

然后#在调用函数的所有.c文件中包含此头文件。

不清楚为什么“2000年以前的c语言规范”-上一个标准是在1999年最终确定的。在此之前,
inline
根本不是关键字

1999年标准规定:

如果所有文件范围声明 对于翻译单元中的函数 包括
内联
功能 不带外部的说明符,则 该翻译单位中的定义为 内联定义。内联定义 该定义未提供详细说明 函数的外部定义, 并且不禁止外部的 另一译本中的定义 一个内联定义提供了一个 替代外部定义, 翻译人员可以使用它来 在中实现对函数的任何调用 T