在C ++中,我可以在头文件中内联声明一个getter函数:
class Cpp_Example
{
public:
unsigned int get_value(void)
{ return value;}
private:
unsigned int value;
};
通过包含此头文件,客户端方法和函数可以使用getter函数来访问私有变量。
我希望用C语言对这个概念进行建模:
hello.h:
#ifndef HELLO_H
#define HELLO_H
#include <stdio.h>
inline void Print_Hello(void)
{
extern const char hello_text[32];
puts(hello_text);
}
inline void Print_Value(void)
{
extern unsigned int value;
printf("Value is: %d\n", value);
}
#endif // HELLO_H
hello.c:
const char hello_text[32] = "Hello World!\n";
static unsigned int value = 5U;
main.c:
#include <stdio.h>
#include <stdlib.h>
#include "hello.h"
int main(void)
{
Print_Hello();
Print_Value();
// puts(hello_text);
return EXIT_SUCCESS;
}
我从gcc收到链接器错误:
$ gcc -o main.exe main.c hello.c
/tmp/cc41ZB8H.o:main.c:(.rdata$.refptr.value[.refptr.value]+0x0): undefined reference to `value'
collect2: error: ld returned 1 exit status
有没有办法让内联函数(在头文件中)访问另一个翻译单元中的静态变量?
或者有没有办法实现内联的getter函数?
我在嵌入式平台上使用IAR Embedded Workbench,ARM7TDMI处理器 gcc编译器用于测试PC上的概念。
编辑1:背景
我正在寻找优化关键部分内的getter调用。目标是减少在关键部分花费的时间。
编辑2:无全局
我们的商店使用的编码指南没有全局变量
此外,该系统是运行MicroCOSII的RTOS。
答案 0 :(得分:2)
首先,与在C ++中使用私有变量的方式相同,您可能意味着拥有struct
而非全局变量的私有变量。有了这个假设,这里有一个你可以使用的模型:
/* some_type.h */
struct some_type
{
int public_data;
void *privates;
};
struct some_type_privates
{
char hello[32];
int value;
};
inline const char *get_hello(struct some_type *t)
{
struct some_type_privates *p = t->privates;
return p->hello;
}
inline int get_value(struct some_type *t)
{
struct some_type_privates *p = t->privates;
return p->value;
}
/* similarly for setters */
与私有变量及其getter和setter在头文件中的方式相同,您也可以在C中执行此操作。
另一方面,我建议不要尝试在C语言中编写C ++。虽然C ++喜欢使事情复杂化以防止白痴破坏某些东西,但另一方面C相信程序员有一定程度的智能。这些假设是否合理不是讨论的问题。但我的意思是,C的精神不是隐藏变量,以致程序员不会错误地访问它。
也就是说,这就是你通常在C中创建结构的方式:
struct some_type
{
int public_data;
char hello[32]; /* read only */
/* internal */
int value;
};
(当然有足够的文档)告诉任何程序员她不应该写hello
但是可以自由地阅读它(你试图通过内联getter实现的)。它还告诉value
是私有的,所以程序员不应该读或写它。
您可以在许多带有或返回结构的POSIX函数中看到这一点。有些不需要控制访问权限的人可以自由修改结构,例如stat
。有些需要检查输入的人有设置器,例如pthread_attr_*
。
答案 1 :(得分:1)
您需要删除static
关键字。 static
定义为local to the compilation unit。
答案 2 :(得分:0)
正如Shabbas所写,它在C中并没有真正起作用。 关键字 inline 意味着静态,即使编译器实际上没有内联它。如果它是如此短的功能,它可能会内联它。但关键是,如果它不是静态的,它甚至不能考虑内联它,因为函数需要在外部可见,它需要一个地址,内联函数没有。 由于它在编译单元中是本地的,因此它只能处理编译单元内部已知的内容。因此你需要说一下 value 变量,就像你需要在C ++标题中提到它一样,只有在C中没有 private 这样的东西。 您不能在相同的情况下使用内联和数据隐藏,既不能在C中也不能在C ++中。
答案 3 :(得分:0)
假设您的意思是全局的,静态分配的变量,您可以这样做:
在Example.h中:
#ifndef Example
#define Example
extern int getValue();
#endif
在Example.c中
#include "Example.h"
static int value;
inline int getValue() {
return value;
}
// All the functions in Example.c have read/write access
在UsesValueExample.c
中#include "Example.h"
// All the functions in UsesValueExample.c have read-only access
void printValue() {
printf("value = %d", getValue());
}
如果您想获得幻想并强制所有代码通过getter和setter访问,例如如果变量是volatile,并且你想大力鼓励所有方法使用变量的本地缓存来避免访问volatile的开销,那么:
在VolatileExample.h中:
#ifndef VolatileExample
#define VolatileExample
extern int getValue();
#endif
在VolatileExample.c中
#include "VolatileExample.h"
void setValue(); // Forward declaration to give write access
// All the functions in VolatileExample.c have read/write access via getters and setters
void addToValuesAndIncrementValue(int const values[], int const numValues) {
int value = getValue(); // Cache a local copy for fast access
// Do stuff with value
for (int i = 0; i < numValues; i++) {
values[i] += value;
}
value++;
// Write the cache out if it has changed
setValue(value);
}
// Put the definitions after the other functions so that direct access is denied
static volatile int value;
inline int getValue() {
return value;
}
inline void setValue(int const newValue) {
value = newValue;
}
在UsesVolatileValueExample.c
中#include "VolatileExample.h"
// All the functions in UsesVolatileValueExample.c have read-only access
void printValue() {
printf("value = %d", getValue());
}
答案 4 :(得分:0)
这是我用来隐藏全局变量的模式。
在某些头文件中,例如module_prefix.h
,您声明以下内容:
typedef int value_t; // Type of the variable
static inline value_t get_name(void) __attribute__((always_inline));
static inline void set_name(value_t) __attribute__((always_inline));
static inline value_t get_name(void) {
extern value_t module_prefix_name;
return module_prefix_name;
}
static inline void set_name(value_t new_value) {
extern value_t module_prefix_name;
module_prefix_name = new_value;
}
/* Note that module_prefix_name is *no longer* in scope here. */
当然,您必须在某些编译单元中定义module_prefix_name
,不使用 static
关键字,如上所述,例如在module_prefix.c
中,您有以下内容:
#include "module_prefix.h"
value_t module_prefix_name = MODULE_PREFIX_NAME_INIT_VALUE;
这与Thomas Matthews尝试使用的模式基本相同,深入了解本质并确保编译器始终内联函数,并且不会不必要地生成显式函数体。注意使用module_prefix
作为穷人的名字空间。