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

こんにちは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

インライン関数 (ヘッダー ファイル内) が別の翻訳単位の静的変数にアクセスする方法はありますか?

または、インラインのゲッター関数を実装する方法はありますか?

組み込みプラットフォームで IAR Embedded Workbench、ARM7TDMI プロセッサを使用しています。
gcc コンパイラは、PC 上で概念をテストするために使用されます。

編集 1: 背景
クリティカル セクション内にある getter 呼び出しを最適化しようとしています。目的は、クリティカル セクションで費やされる時間を短縮することです。

編集 2: グローバルなし
当店が使用するコーディング ガイドラインには、グローバル変数はないと記載されています。
また、このシステムは MicroCOSII を実行する RTOS です。

4

5 に答える 5

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、いくつかのコンパイル単位で定義する必要があります。たとえば、次のようになります。staticmodule_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 に答える