|
之前浏览论坛,看到有用“掩码结构体”的方式实现struct成员的隐藏,这样用户就只能通过指定接口来访问struct成员数据,从而在一定程度上实现了信息隐藏,但是“掩码结构体”方法需要在引入一组宏定义,同时需要在xxx.c文件和xxx.h文件中写一遍struct的定义(当然复制一下也方便),但是最头疼的是,有时在一处修改了struct的定义,而另一处忘了修改,但是编译时并不会报错,而运行时会出错。
今天偶然看到“不透明指针”的概念,发现可以实现与“掩码结构体”类似的效果。
其实,这个方法我之前也用过,但是不知道还有“不透明指针”的这一概念。
首先,必须要说明一下,C的struct中成员本身是公开的,所有C编程的奇技淫巧,只是实现形式上的隐藏,并不能真正彻底的隐藏数据。
比如:
- struct DevLed
- {
- uint8_t state;
- char *name;
- };
复制代码
然后现在有一个指针p指向一个具体的DevLed结构体对象
所谓”形式上的隐藏“是指:在外部文件试图通过p->state来访问struct中的成员,编译时会报错,从而“强制”用户通过指定的接口来访问数据,因此实现了信息的隐藏和访问权限控制。
所谓“并不能真正彻底的隐藏数据”是指:在C语言中,如果获得了一个对象的指针(内存地址),那么就可以获得相应的数据,比如使用 *((uint8_t *)p)就可以获得成员state。当然实际情况下,由于用户并不清楚结构体中成员信息,所以虽然获得了数据,但是这些数据代表什么含义,那就靠猜了。但是,多猜几次总归还是可以猜出来了。所以说,C语言中的这些隐藏方法是“防君子不防小人”。
那不管怎样,有总比没好,而且“不透明指针”方法比“掩码结构体”方法,使用起来更加方便点。
- /*led.h*/
- #ifndef __LED_H
- #define __LED_H
- //供用户使用的类型
- //DevLed_t就是所谓的“不透明指针”
- typedef struct DevLed * DevLed_t;
- //供用户使用的接口
- extern DevLed_t DevCreate(void);
- extern uint8_t DevRead(DevLed_t s);
- extern void DevWrite(DevLed_t s, uint8_t arg);
- #endif
复制代码
- /*led.c*/
- #include <stdint.h>
- #include <stdlib.h>
- //DevLed结构体定义
- struct DevLed
- {
- uint8_t state;
- };
- typedef struct DevLed * DevLed_t;
- //接口的具体实现
- DevLed_t DevCreate(void)
- {
- //注意,此处演示用了malloc动态内存分配,但也可以用静态分配
- DevLed_t s = (DevLed_t)malloc(sizeof(struct DevLed));
- if (NULL != s)
- s->state = 0;
- return s;
- }
- uint8_t DevRead(DevLed_t s)
- {
- return s->state;
- }
- void DevWrite(DevLed_t s, uint8_t arg)
- {
- s->state = arg;
- }
复制代码
- /*main.c*/
- #include <stdio.h>
- #include <stdint.h>
- #include "led.h"
- int main()
- {
- //创建对象并获取指针
- DevLed_t me = DevCreate();
- printf("readout = %d\n", DevRead(me));
- DevWrite(me, 10);
- printf("readout = %d\n", DevRead(me));
- //防君子不防小人,故意采用这种方式,也是可以获取数据的
- printf("readout = %d\n", *((uint8_t *)me));
- //直接访问me->state编译会报错,实现形式上的隐藏
- //printf("readout = %d\n", me->state);
- getchar();
- return 0;
- }
复制代码
|
阿莫论坛20周年了!感谢大家的支持与爱护!!
一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。
|