C私有变量获取和设置方法

Rei*_*eid 9 c private-members private-methods

我在C中工作,并且有一些我不想成为全局的变量,但我确实想要获取和设置它们的方法,可以在文件外部访问"Globaly".我习惯在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;
}
Run Code Online (Sandbox Code Playgroud)

San*_*raj 15

你做变量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;
}
Run Code Online (Sandbox Code Playgroud)

文件名:header.h

#include <stdio.h>

int get(void);
void set(int);
Run Code Online (Sandbox Code Playgroud)

文件名:header.c

#include "header.h"

static int value = 0;

int get(void)
{
    return value;
}

void set(int new_value)
{
    value = new_value;
}
Run Code Online (Sandbox Code Playgroud)

输出:

$ gcc -Wall -o main main.c header.h header.c 
$ ./main 
value = 10 
value = 20 
value = 30 
value = 40 
$ 
Run Code Online (Sandbox Code Playgroud)

  • 不需要在标题中包含`stdio.h`. - 标头中的代码不使用它. (4认同)
  • 不需要在`main.c`的顶部声明`get()`和`set()`. - 这就是你首先创建标题的原因. (3认同)

Edw*_*uck 8

如果你想在c中使用私有变量,有许多技术可以近似私有变量,但是C语言实际上没有"保护"概念,它扩展到私有,公共,受保护(如C++那样).

C将显示任何变量的名称(这是C中的要求),因此您必须以隐藏变量类型的信息(使解除引用非常困难)的方式接近它.

一个技巧是将变量定义void*只有一个.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".
Run Code Online (Sandbox Code Playgroud)

一个更好的方法是使用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;
 }
Run Code Online (Sandbox Code Playgroud)

像这样的技术有几个变体,一个是有一个"公共结构",带有指向"私有结构"的void*指针.一种是将"方法"作为函数指针包含在"公共结构"中(支持多态性的一步),一种是实际编写一个完整而恰当的C++类型系统,它试图像C++那样完全解决问题(类层次结构,多态性,后期绑定,信息隐藏等).

基本上,你可以得到一些"面向对象性"没有太多的工作,但是当你添加的-ornamentation更多的功能,你将增加更多的胶水代码(直到它简单得多的实际使用面向对象的编程语言) .