Getter 用于 C 中的只读变量
Getter for a read-only variable in C
我正在写一个库。这个库有一个 init()
函数来初始化一些内部变量。这些变量必须可以从外部访问,但只能是只读的。
因为我在嵌入式设备上工作,它太庞大了,无法拥有真正的 getter 功能。
除了这两个我还能用什么好的解决方案(假设它们都是不好的解决方案):
使用 inline
getter(其中 _internal_parameter
不能是 static
):
inline int get_parameter() { extern int _interal_parameter; return _internal_parameter; }
使用 const
(其中 const
变量并未真正受到保护):
// lib.c
void init() {
*(int*)¶meter = get_value_for_parameter();
}
// lib.h
extern const int parameter //!< initialized by init();
c没有很好的封装方式
真正的封装只能通过使变量static
,并使用非内联getter来访问它来实现。这将始终 return 所述变量的副本。
你的第二个版本是未定义的行为。
在 C 中,使数据私有化的唯一方法是将其隐藏在编译单元中。
这可以通过使用静态变量(如果变量是全局变量)或通过在将使用它的编译单元中定义结构来实现。
然后您可以声明一个非静态函数,该函数 returns 通过值或 const 引用(使用 const 指针)获取值。这将迫使您创建一个普通函数。内联将无济于事,因为变量隐藏在编译单元中。
如果函数的开销太高,您将被迫将变量声明为非静态变量(或声明您的结构)。在这种情况下,没有什么可以阻止您的用户更改变量。
可能还有第三种方法,那就是将您的变量声明为静态的,然后创建一个指向将在函数外部公开的变量的非静态常量指针。在这种情况下,用户仍然可以使用强制转换进行修改。
不清楚为什么使用真正的 getter 函数会很昂贵。听起来好像您的编译器没有正确进行内联。此外,函数调用开销的无效性通常被大大夸大了,除非您使用的是一些古老的 MCU 架构。
最优当然是:
//lib.c
int get parameter (void)
{
return parameter;
}
或者,如果函数调用真的太昂贵并且您找不到修复内联的方法,getter 可以 return 和 const int*
。在调用者中使用局部指针变量,然后只调用 getter 一次。
请注意,在任何嵌入式系统上使用 int
几乎肯定是不正确的做法。而是使用有意义的最小类型。一定要签字吗?说 "my application is so real-time critical that I can't even call functions" 然后在代码中乱扔一个草率的 int
真的没有意义。
你应该避免extern const
除非变量是真正的只读变量(比如闪存中的常量)。
我正在写一个库。这个库有一个 init()
函数来初始化一些内部变量。这些变量必须可以从外部访问,但只能是只读的。
因为我在嵌入式设备上工作,它太庞大了,无法拥有真正的 getter 功能。
除了这两个我还能用什么好的解决方案(假设它们都是不好的解决方案):
使用 inline
getter(其中 _internal_parameter
不能是 static
):
inline int get_parameter() { extern int _interal_parameter; return _internal_parameter; }
使用 const
(其中 const
变量并未真正受到保护):
// lib.c
void init() {
*(int*)¶meter = get_value_for_parameter();
}
// lib.h
extern const int parameter //!< initialized by init();
c没有很好的封装方式
真正的封装只能通过使变量static
,并使用非内联getter来访问它来实现。这将始终 return 所述变量的副本。
你的第二个版本是未定义的行为。
在 C 中,使数据私有化的唯一方法是将其隐藏在编译单元中。 这可以通过使用静态变量(如果变量是全局变量)或通过在将使用它的编译单元中定义结构来实现。
然后您可以声明一个非静态函数,该函数 returns 通过值或 const 引用(使用 const 指针)获取值。这将迫使您创建一个普通函数。内联将无济于事,因为变量隐藏在编译单元中。
如果函数的开销太高,您将被迫将变量声明为非静态变量(或声明您的结构)。在这种情况下,没有什么可以阻止您的用户更改变量。
可能还有第三种方法,那就是将您的变量声明为静态的,然后创建一个指向将在函数外部公开的变量的非静态常量指针。在这种情况下,用户仍然可以使用强制转换进行修改。
不清楚为什么使用真正的 getter 函数会很昂贵。听起来好像您的编译器没有正确进行内联。此外,函数调用开销的无效性通常被大大夸大了,除非您使用的是一些古老的 MCU 架构。
最优当然是:
//lib.c
int get parameter (void)
{
return parameter;
}
或者,如果函数调用真的太昂贵并且您找不到修复内联的方法,getter 可以 return 和 const int*
。在调用者中使用局部指针变量,然后只调用 getter 一次。
请注意,在任何嵌入式系统上使用 int
几乎肯定是不正确的做法。而是使用有意义的最小类型。一定要签字吗?说 "my application is so real-time critical that I can't even call functions" 然后在代码中乱扔一个草率的 int
真的没有意义。
你应该避免extern const
除非变量是真正的只读变量(比如闪存中的常量)。