13

私はCで作業しており、グローバルにしたくない変数がいくつかありますが、ファイルの外部で「グローバルに」アクセスできるgetメソッドとsetメソッドが必要です。私は Java でこれを行うことに慣れていますが、C はこの点で大きく異なります。基本的に、私はこの疑似コードに従うものを探していますが、私が見るかもしれない例でどこにも見つけることができませんでした.

main.c
#include data.h
set(b);

datalog.c
#include data.h
get(b);

data.c
private int c;
set(b){
    c = b;
}
get(c){
    return c;
}
4

6 に答える 6

19

変数を作成しますstatic。グローバル変数が作成されるstaticと、そのスコープは現在のファイルに制限されます。

例は次のとおりです。

ファイル名: main.c

#include <stdio.h>

#include "header.h"

extern int get();
extern void set(int);

int main()
{
    set(10);
    printf("value = %d \n", get());   
    set(20);
    printf("value = %d \n", get());   
    set(30);
    printf("value = %d \n", get());   
    set(40);
    printf("value = %d \n", get());   
    return 0;
}

ファイル名: header.h

#include <stdio.h>

int get(void);
void set(int);

ファイル名: header.c

#include "header.h"

static int value = 0;

int get(void)
{
    return value;
}

void set(int new_value)
{
    value = new_value;
}

出力:

$ gcc -Wall -o main main.c header.h header.c 
$ ./main 
value = 10 
value = 20 
value = 30 
value = 40 
$ 
于 2012-04-25T16:47:03.603 に答える
9

c でプライベート変数が必要な場合は、プライベート変数を近似できる手法がいくつかありますが、C 言語には、(C++ のように) プライベート、パブリック、プロテクトに拡張される「保護」の概念が実際にはありません。

C は任意の変数の名前を表示します (これは C の要件です)。そのため、変数のを隠す情報 (逆参照を非常に困難にする)のアイデアを使用してアプローチする必要があります。

1 つのトリックは、変数を として定義void*し、実際の変数の型が 1 つの.cモジュールでのみ認識されるようにすることです。

 /* somefile.h */

 extern void* counter; 

 /* somefile.c */

 #include "somefile.h"

 int actualCounter = 0;
 void* counter = &actualCounter;

 /* otherfile.c */

 #include "somefile.h"

 // we can see "counter", but we cannot "use" it here; because we don't have access
 // to the real "hidden" type of "int".

より良い方法は、structキーワードを使用してこのアイデアを拡張し、次のように疑似メソッドを作成することです。

 /* person.h */

 struct s_person;

 typedef Person struct s_person;

 Person* new_Person(char* name);
 void delete_Person(Person* person);

 void Person_setName(Person* person, char* name);
 char* Person_getName(Person* person);

 /* person.c */

 struct s_person {
   char* name;
 };

 Person* new_Person(char* name) {
   Person* object = (Person*)malloc(sizeof(struct s_person));
   // duplicate the string for more security, otherwise constructor
   // could manipulate the "private" string after construction.
   object->name = strdup(name);
   return object;
 }

 void delete_Person(Person* person) {
   // some implementations pass a Person** to set the reference to 0
   // this implementation requires that the caller sets his own references to 0
   free(person->name);
   free(person);
 }

 void Person_setName(Person* person, char* name) {
   // free the old
   free(person->name);
   // duplicate the new to provide "out of simulated class" modification by malicious 
   // name setter.
   person->name = strdup(name);
 }

 char* Person_getName(Person* person) {
   // must return a copy, otherwise one can manipulate name
   // from reference provided by Person_getName(...);
   return strdup(person->name);
 }

 /* otherfile.c */

 #include "Person.h"

 /* Now we can hold Person "simulated objects", but we cannot */
 /* manipulate their "state" without using the C simulated object */
 /* methods */

 int main(int argc, char** argv) {

   Person* bob = new_Person("bob");
   printf("%s\n", Person_getName(bob));
   delete_Person(bob);
   // critical or we hold a pointer to freed memory.
   bob =  0;

   return 0;
 }

このような手法にはいくつかのバリエーションがあります。1 つは、「プライベート構造体」への void* ポインターを持つ「パブリック構造体」を持つことです。1 つは「メソッド」を「public struct」に関数ポインタとして含めること (ポリモーフィズムをサポートするためのステップ) です。もう 1 つは、C++ とまったく同じように物事を解決しようとする完全かつ適切な C++ 型システムを実際に記述することです (クラス階層、ポリモーフィズム、レイト バインディング、情報隠蔽など)。

基本的に、あまり手間をかけずに「オブジェクト指向性」を得ることができますが、装飾の機能を追加すると、グルー コードが追加されます (オブジェクト指向プログラミング言語を実際に使用する方はるかに簡単になるまで)。 .

于 2012-04-25T16:45:03.190 に答える
2

次のように入力できます。

static int c;

このように、「.o」は「c」変数をエクスポートしません。

于 2012-04-25T16:41:07.117 に答える
1
static int c;

int get(void) {
    return c;
}

int set(int n) {
    c = n;
}
于 2012-04-25T17:02:01.057 に答える
1

あなたの例では、structこの情報でいくつかを使用してみることができます。Astructは、publicメンバー変数classのみを持つ(つまり、関数がない) のようなものです。したがって、次のように考えてください

#include <stdio.h>

typedef struct _somestruct
{
  int c;
} theStruct;

int getC(theStruct* obj)
{
  if(obj == NULL)
    return -1;
  return obj->c;
}

void setC(theStruct* obj, int val)
{
  if(obj == NULL)
    return;
  obj->c = val;
}

int main()
{
  theStruct myStruct;
  setC(&myStruct, 5);
  printf("%d\n", getC(&myStruct));
  return 0;
}

ご覧のとおり、Cはオブジェクトと関数でのみ機能します。ただし、すべてのファイルでグローバル変数を取得するには、試してくださいstatic int c = 0;

上記の例は、「Java スタイル」の規則にほぼ近いものです。

于 2012-04-25T16:48:29.230 に答える