前些天看一款数据库语法解析器的代码,其中的词法分析语法解析阶段,利用一个结构体存储所解析的SQL语句的类型,然后根据这个类型将改结构体强制转换为对应的另一结构体并赋值给他,以便做进一步的执行工作。
举个简单的例子:
存储语法解析后数据的结构体(注意,其只有一个元素)为:
struct analyse { int type; };
我们约定的不同的type代表不同的SQL操作,假如type=1时表示alter table操作,type=2时表示select操作,type等于3时表示create table操作等等。那么我们对不同的操作有不同的结构体来存储信息,例如:
struct alter { int type; int number; char subtype; ...... ......
};
struct select { int type; char relnum; long tablenum; ...... ......
};
注意到,结构体analyse,alter与select中第一个元素的类型都是一样的,表示的意思也相同,都是代表不同的操作号。现在若判断analyse中的type为1时,将其强制转换为struct alter并赋值给struct alter类型的变量;若判断analyse中的type为2时,将其强制转换为struct select并赋值给struct select类型的变量。
可能有人会问了,为什么程序里要对类型不同的结构体之间强制转换并赋值呢?
问题解析
问题的关键在于,结构体struct analyse中的type存储不同的值时,在紧挨着结构体的内存中按照要强制转换的结构体的元素类型存储了相对应的数据。
例如,当结构体struct analyse中的type为1时,需要在紧挨着结构体struct analyse的高地址区域按照结构体struct alter的数据类型存储对应的数据,包括int,char等等。当结构体struct analyse中的type为2时,需要在紧挨着结构体struct analyse的高地址区域按照结构体struct select的数据类型存储对应的数据,包括char,long等。
这样,在进行强制转换时,结构体struct analyse与结构体struct analyse中除了int type以外的那些元素可以得到相对应的值了。
简单的小例子
下面是一个简单的小例子,说明了该强制转换的问题:
struct A{ int num; };
struct B{ int num; char type; int age; };
int main() { struct A a; a.num=1;
char* tmp1=(char *)(&(a.num)); tmp1=tmp1+4; *tmp1='a'; int *tmp2=(int *)(&(a.num)); tmp2=tmp2+2; *tmp2=100;
struct B *b=(struct B *)(&a);
printf(" b->num=%d b->type=%c b->age=%d ",b->num,b->type,b->age); }