没有malloc AVR的共享指针

时间:2015-04-30 12:03:52

标签: c pointers embedded avr

标题可能不清楚,所以我举一个例子。

我正在尝试在C中建立一个“数据流”系统。

输入STREAM

typedef struct {
    void (*tx) (uint8_t b);
    uint8_t (*rx) (void);
} STREAM;

我有uart.h文件uart.c,应为UART提供STREAM

我决定最好将它作为指针公开,因此可以在不使用&符号的情况下传递给函数。

这是我想用它的一种功能(例子):

/** Send signed int */
void put_i16(const STREAM *p, const int16_t num);

这是我的UART文件:

uart.h

extern STREAM* uart;

uart.c

// Shared stream instance
static STREAM _uart_singleton;
STREAM* uart;

void uart_init(uint16_t ubrr) {
    // uart init code here

    // Create the stream
    _uart_singleton.tx = &uart_tx; // function pointers
    _uart_singleton.rx = &uart_rx;

    uart = &_uart_singleton; // expose a pointer to it
}

我不确定这一点。它有效,但这是正确的方法吗?我应该只使用Malloc吗?

为什么我问这个,它是一个库代码,我希望它尽可能干净和“正确”

1 个答案:

答案 0 :(得分:3)

全局指针是不必要的(as are all globals),而且不安全 - 它是非常量的;任何有权访问指针的代码都可以修改_uart_singleton

uart.h

const STREAM* getUart() ;
...

uart.c

// Shared stream instance
static STREAM _uart_singleton = {0} ;

const STREAM* getUart()
{
    // Return singleton if initialised, 
    // otherwise NULL
    return _uart_singleton.rx != 0 && 
           _uart_singleton.tx != 0 ? _uart_singleton :
                                     NULL ;
}

void uart_init(uint16_t ubrr) 
{
    // uart init code here

    // Create the stream
    _uart_singleton.tx = &uart_tx; // function pointers
    _uart_singleton.rx = &uart_rx;
}

只要访问STREAM成员的所有函数都使用uart.c定义,那么您还可以通过使用STREAM成为 opaque类型(Lundin在评论中的建议)标题中的不完整的结构声明因此:

uart.h

struct sStream ;
typedef struct sStream STREAM ;

const STREAM* getUart() ;
...

uart.c

// Shared stream instance
struct sStream 
{
    void (*tx) (uint8_t b);
    uint8_t (*rx) (void);

} _uart_singleton = {0} ;

const STREAM* getUart()
{
    // Return singleton if initialised, 
    // otherwise NULL
    return _uart_singleton.rx != 0 && 
           _uart_singleton.tx != 0 ? _uart_singleton :
                                     NULL ;
}

...

这可以防止uart.c之外的任何代码直接调用rxtx函数或访问任何其他成员。