2014-01-24 30 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作爲窮人的名字空間。