当在一个很大的工程中,需要隐藏结构体中的内容,或者中间件给用户的接口,不希望用户知道结构体的内容形式,那么,请使用前置定义。
先上一个小例子:
//main.c
#include <stdio.h>
#include "test.h"
struct Test *test;
void main(void)
{
int ret;
test = Init();
Print(test);
printf("the end!\n");
}
//test.h
#ifndef _TEST_H_
#define _TEST_H_
struct Test *Init(void);
void Print(struct Test * test);
#endif
//test.c
#include <stdio.h>
#include <stdlib.h>
struct Test
{
char num;
int flag;
};
typedef struct Test *TEST;
TEST Init(void)
{
TEST test;
test = (TEST)malloc(sizeof(struct Test));
test->flag = 9;
test->num = 4;
rerurn test;
}
void Print(TEST test)
{
printf("the result is %d,%d!\n", test->num, test->flag);
free(test);
}
例子比较简单,就三个文件,其中main.c和test.h可以提供给别人,为了隐藏struct Test结构体中的内容,将test.c文件编译成库文件。
编译过程:
第一步:
gcc -o libtest.so -fPIC -shared test.c
第二步:
gcc -o test main.c -L ./ -l test
第三步:
export LD_LIBRARY_PATH=./
第四步:
执行程序 ./test
不出什么意外会打印出正确结果,以上操作不需要root权限。这时候,你将test.c文件移走,别人就不会知道struct Test中到底有什么东西了,能够在一定程度上实现结构体数据的保密。
注意点:
(1)在main.c中定义结构体的时候,要定义成指针型变量;如果定义成为非指针变量(如struct Test test),那么会报出“incomplete type”的错误。因为定义成为非指针变量的话,程序在编译的时候会给变量分配空间,但是该变量是一个“前置定义”的变量,不知道包还有什么元素,所以会报错;定义成为一个指针后,直接分配一个地址完事。
(2)既然是“incomplete type”,在main.c中是不能够使用sizeof求出结构体的大小,即sizeof(struct Test)会报错。
(3)在main函数中定义的test指向NULL,所以不能够直接使用,通过malloc分配内存后使用。
(4)切记不要这么用:
void Init(sruct Test *test);
…
void Init(struct Test *test)
{
…
test = (struct Test *)malloc(sizeof(struct Test));
…
}
这样的话,在main函数中调用Init函数,不会得到正确的结果。
敲代码的路上需要积累,共勉。