2014-01-24 32 views
2

在C++中,我可以有一个吸气函数声明在头文件中的内联:内联setter和getter功能用C

class Cpp_Example 
{ 
    public: 
    unsigned int get_value(void) 
    { return value;} 
    private: 
    unsigned int value; 
}; 

通过包含该头文件,客户端的方法和功能可以使用吸气剂功能访问私有变量。

我期待这个概念在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

@chux:去除静态破坏封装和数据隐藏。该变量成为任何人都可以访问的全局变量。 –

+1

如果您保持静态,则无法从外部访问它。请记住C中没有名称空间,并且第一个C编译器的连接器在符号中不支持超过6个字符(即变量名称/函数名称)。为了避免污染非常有限的全局名称空间,“静态”关键字(函数之外)被发明了*来隐藏对象。所以从外部访问对象的任何方式都会违背静态的意图。 –

回答

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

您需要删除static关键字。 static的定义是local to the compilation unit

+0

我想将变量保持为私有的而不是全局变量;类似于C++类的概念。删除静态关键字违反了这个概念。 –

+0

然后将函数放入hello.c中并导出函数。 – perreal

+1

然后它不再是内联,所以调用它更昂贵。 –

0

由于Shabbas写道,它并没有真正工作的方式中C. 关键字直列意味着静态,即使编译器实际上并没有内联它。如果它是如此短的功能,它可能会内联。但重点是,如果它不是静态的,它甚至不会考虑将其内联,因为该功能需要在外部可见,所以需要一个内联函数没有的地址。 由于它在编译单元中是本地的,因此它只能在该编译单元内已知的东西上工作。因此,你需要说一些关于变量的内容,很像你需要在C++头文件中提及它,只有在C中不存在私有文件。 无论是在C语言还是在C++中,都无法在同一大小写中嵌入和隐藏数据。

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来访问,例如如果变量是挥发性的,并要大力鼓励所有的方法来使用该变量的本地缓存,以避免访问挥发,然后的开销:

在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()); 
} 
+0

我的理解是,在头文件中声明变量,尤其是'static',将在包含头文件的每个源文件中创建一个实例。 –

+0

在C静态是你如何做私人静态分配的变量。我知道语法是错误的, –

+0

偶然发布了。在C静态文件范围变量中,静态的正常含义是静态的,意味着私有变量。奇怪我知道,但事情就是这样!注意我在.c实现文件中使用了静态,而不是在声明头文件中.h文件中,而不是在使用.c文件中。 –

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; 

这实质上是托马斯·马修斯试图用,向下钻取到的精髓,并确保编译器内联始终的功能,并不一定会产生明确的函数体相同的模式。请注意使用module_prefix作为穷人的名字空间。