标题可能不太清楚,我举个例子。
我正在尝试用 C 语言创建一个“数据流”系统。
输入STREAM
:
typedef struct {
void (*tx) (uint8_t b);
uint8_t (*rx) (void);
} STREAM;
我有一个带有 uart.c
的文件 uart.h
,它应该为 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 吗?
为什么我问这个,它是一个库代码,我希望它尽可能干净和“正确”
最佳答案
全局指针是不必要的( 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 成为不透明类型中受益(Lundin 在评论中的建议)通过在 header 中使用不完整的结构声明:
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 之外的任何代码直接调用 rx
和 tx
函数或访问任何其他成员。
关于c - 没有 malloc AVR 的共享指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29967303/