2

在 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

你好ç:

const char hello_text[32] = "Hello World!\n";

static unsigned int value = 5U;

主.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。

4

5 回答 5

2

首先,就像你在 C++ 中拥有私有变量一样,你可能意味着拥有 astruct而不是全局的私有变量。有了这个假设,这是您可以使用的一个模型:

/* 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但可以自由阅读它(你试图通过内联吸气剂实现的目标)。它还告诉它value是私有的,因此程序员不应该读取或写入它。

您可以在许多接受或返回结构的 POSIX 函数中看到这一点。一些不需要控制访问的可以让你自由修改结构体,比如stat. 一些确实需要检查输入的有设置器,例如pthread_attr_*.

于 2014-01-24T18:26:34.530 回答
1

您需要删除static关键字。static定义对编译单元来说是本地的

于 2014-01-24T18:19:43.723 回答
0

正如 Shabbas 所写,它在 C 中并没有真正以这种方式工作。关键字inline意味着static,即使编译器实际上并没有内联它。如果它是这么短的函数,它可能会内联它。但关键是,如果它不是静态的,它甚至不能考虑内联它,因为函数需要在外部可见,它需要一个地址,而内联函数没有。由于它在您的编译单元中是本地的,因此它只能处理该编译单元内已知的内容。因此,您需要对该变量说些什么,就像您确实需要在 C++ 标头中提及它一样,只有在 C 中没有私有这样的东西. 在 C 和 C++ 中都不能在相同的情况下进行内联和数据隐藏。

于 2014-03-19T01:35:56.373 回答
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());
}
于 2014-11-27T07:19:38.440 回答
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作为穷人的名称空间的使用。

于 2016-03-13T15:15:43.260 回答