Chinaunix

标题: 请问如何通过结构体的基地址和偏移来操作其成员变量? [打印本页]

作者: lxyscls    时间: 2011-11-10 15:35
标题: 请问如何通过结构体的基地址和偏移来操作其成员变量?
struct xx{
    int a;
    char *b;
    char *c;
};

如果通过该结构体的基础地址+偏移来对a,b,c这些成员进行操作?

能不能就我这个结构体给个例子?
作者: file3    时间: 2011-11-11 09:52
这个最好不要这么做!

因为大家都知道结构体成员的地址对齐问题,在不同的系统上 结构体的成员地址的对齐方式是不一样的。


gcc中有个扩展可以 调整结构体成员的地址对齐方式。所以,这样的结果可能是不可预料的。
作者: samzc2010    时间: 2011-11-11 10:29
本帖最后由 samzc2010 于 2011-11-11 10:31 编辑
  1. baseAddr + (unisigned long)(&(((type*)0)->member))
复制代码
你这是干嘛?没事找抽啊。

回复 1# lxyscls
作者: 狗蛋    时间: 2011-11-11 12:52
C's offsetof() macro is an ANSI C library feature found in stddef.h. It evaluates to the offset (in bytes) of a given member within a struct or union type, an expression of type size_t. The offsetof() macro takes two parameters, the first being a structure name, and the second being the name of a member within the structure. It can not be described as a C prototype.

http://en.wikipedia.org/wiki/Offsetof
作者: yulihua49    时间: 2011-11-11 14:22
struct xx{
    int a;
    char *b;
    char *c;
};

如果通过该结构体的基础地址+偏移来对a,b,c这 ...
lxyscls 发表于 2011-11-10 15:35



    通过模板映射结构。目前处理结构里的指针还是有困难。
作者: samzc2010    时间: 2011-11-11 14:50
方法参见3楼,书不行的也请参见3楼方法。
作者: gtkmm    时间: 2011-11-12 03:39
好像内核里的那个, 双链表就用这个东西了.
作者: lxyscls    时间: 2011-11-15 21:35
好像内核里的那个, 双链表就用这个东西了.
gtkmm 发表于 2011-11-12 03:39



    内核里面是宏,把struct类型传入了的
作者: lxyscls    时间: 2011-11-15 21:38
你这是干嘛?没事找抽啊。

回复  lxyscls
samzc2010 发表于 2011-11-11 10:29



    1、我想做个通用的函数
   2、是个结构数组,想一次性对该结构数组中数组某成员一次性赋值

   最后我还是屈服了,修改了底层函数,没有用这种方法
作者: caiyijun1987    时间: 2011-11-18 09:56
其实这个并不是不可以,你可以这样定义结构体:
struct xx{
    int a:32;
    char *b:32;
    char *c:32;
};
这样你想杂赋值就杂赋值,32代表32位
作者: keytounix    时间: 2011-11-18 10:28
本帖最后由 keytounix 于 2011-11-18 13:31 编辑

1.
你这个需要考虑编译器优化时候数据的对齐问题不?
如果到这样的结构体
struct M_t
{
char a;
int b;
char *c;
}
会不会出问题?
struct M_t
{
char a;
int b;
char *c;
}__attribute__(aligned(2))
这样 属性弄一下 ,
是否会好一点呢?

2.
个人有点疑惑
既然有指针pst,还有元素m了
pst->m
不就可以弄好了吗?
如果要操作addr开始的size个单 元,
memset(addr,size,0)
不就可以了吗?
作者: yulihua49    时间: 2011-11-18 13:09
本帖最后由 yulihua49 于 2011-11-18 13:34 编辑
1.
你这个要考虑过编译器优化时候数据的对齐问题没啊?
如果到这样的结构体
struct M_t
{
char a;
in ...
keytounix 发表于 2011-11-18 10:28



    提一个问题:
如果你的处理程序与结构没有定义在一起,它不知道你的结构怎么办呢?

比方写一个 struct_to_JSON(to_json,from_struct,....);
对于传进来的struct,并不知道它的具体构造,要生成一个json:
"struct_name":{"成员名1":"值1","成员名2":"值2",......}

以后人们使用这个函数:

struct_to_JSON(json,&my_struct,....);

这时才有了具体的结构。STL能做这事吗?
这我已经做成功了,你有何高招,切磋一下。

透漏一点:

int struct_to_JSON(JSON_OBJECT to_json,void *from_struct,Template *tpl,.......);
当然还可以:
int JSON_from_struct(void *to_struct,JSON_OBJECT json,Template *tpl,.....);
int struct_to_String(char *to_Str,viod *from_struct,Template *tpl,char delimit,...);
int String_to_struct(void *to_struct,char *from_Str,Template *tpl,char delimit,...);

映射数据库:
select_to_struct();
insert_from_struct();
update_from_struct(),........
作者: keytounix    时间: 2011-11-18 13:40
本帖最后由 keytounix 于 2011-11-18 13:45 编辑

回复 12# yulihua49

惭愧

JSON是啥
我刚百度了,
看了很久
没看明白
隔行如隔山啊
作者: yulihua49    时间: 2011-11-18 17:28
本帖最后由 yulihua49 于 2011-11-18 17:30 编辑
回复  yulihua49

惭愧

JSON是啥
我刚百度了,
看了很久
没看明白
隔行如隔山啊
keytounix 发表于 2011-11-18 13:40



    精简的标记语言。
名-值对的数据对象。

形如:"struct_name":{"成员名1":"值1","成员名2":"值2",......}
作者: keytounix    时间: 2011-11-18 17:40
回复 14# yulihua49


    用C语言
除了宏

你能实现这个?
作者: yulihua49    时间: 2011-11-19 09:18
回复  yulihua49


    用C语言
除了宏

你能实现这个?
keytounix 发表于 2011-11-18 17:40

对,已经实现了N多年了。
用模板。

另外楼上,不要把注意力放在JSON上,关键是怎么认识结构,怎么找到名字和值的位置、类型等。
作者: keytounix    时间: 2011-11-19 16:43
本帖最后由 keytounix 于 2011-11-19 16:51 编辑

回复 16# yulihua49


   我的难点在于
用C怎么得到一个结构的名称

比如
struct test
{
int a;
char b;
long c;


}

test t;
t.a=1
t.b=2;
t.c =3;

这个是事实存在的

现在我们并不知道这个test结构体

拥有哪些成员

你是怎么用C得到这个结构体的成员名呢?

还有

我是看谭好强 的C启蒙的

貌似并没看到哪里有说C的什么模版的

倒是C++里面有这个东西

如果你扯上模板了,

我是不是可以说 超出C的范围了?


你怎么知道他的成员名称?
作者: yulihua49    时间: 2011-11-19 21:02
本帖最后由 yulihua49 于 2011-11-19 21:42 编辑
回复  yulihua49


   我的难点在于
用C怎么得到一个结构的名称

比如
struct test
{
int a;
ch ...
keytounix 发表于 2011-11-19 16:43



    的确,C在运行时(就不应该叫C了吧?机器码)是不知道任何结构的,只知道基地址+变址值。
就是说,C的结构,在运行时是不可解析的,在任何未定义的场合是不可能知道的。在需要进行任何内存对象的序列化和反序列化时(我的楼上例子),采用了专用的序列化和反序列化对象,如google的protobuf等等。目前没有见到对C结构进行通用的序列化和反序列化的法(大家帮我查一下,是否有)。
我们在16年前做了这个工作,并在生产环境得到大范围的应用。我一直认为,这是一个突破。

事实上,在做这个工作时,我们关心一个结构里,有多少成员,各是什么类型,多长,在哪?
此外还有各自的名字,显示的格式,其他属性。最后,这个结构总共多长(字节数)。还有,与数据库对应的表名?
哈哈,整个一个数据字典。对,就是数据字典!!!为每一个结构配一个数据字典。为了提高性能,这个数据字典用结构组的形式放在内存,这就是数据模板TEMPLATE。模板一定要C++吗?没人这么说,老谭也没说C不能做模板啊。

#include <datejul.h>

#define CH_BYTE 0
#define CH_CHAR 1
#define CH_TINY 2
#define CH_SHORT 3
#define CH_INT 4
#define CH_LONG 5
#define CH_INT64 6
#define CH_FLOAT 7
#define CH_DOUBLE 8
#define CH_LDOUBLE 9
#define CH_STRUCT 125
#define CH_CLOB 126

extern const char NAN[sizeof(double)];
#define DOUBLENULL (*(double *)NAN)
#define FLOATNULL (*(float *)NAN)
#define SHORTNULL (short)(1<<(8*sizeof(short)-1))
#define INTNULL   (int)(1<<(8*sizeof(int)-1))
#define LONGNULL  (1L<<(8*sizeof(long)-1))
#define INT64NULL  ((INT64)1<<(8*sizeof(INT64)-1))
#define TINYNULL  0X80


/*****************************************************
* define extend data type for net_pack()
*****************************************************/
#define CH_DATE         CH_CHAR|0x80
#define CH_CNUM         CH_CHAR|0x100
#define CH_JUL          CH_INT4|0X80
#define CH_MINUTS       CH_INT4|0x100
#define CH_TIME         CH_INT64|0x80
#define CH_USEC         CH_INT64|0x200
/* used by varchar2 as date(year to day),default format is "YYYYMMDD" */
#define CH_CJUL         CH_INT4|0x200
#define CH_CMINUTS      CH_INT4|0x400
/* used by varchar2 as date(year to sec),default format is "YYYYMMDDHH24MISS" */
#define CH_CTIME        CH_INT64|0x100

#define YEAR_TO_DAY_LEN 11
#define YEAR_TO_MIN_LEN 17
#define YEAR_TO_SEC_LEN 20
#define YEAR_TO_USEC_LEN 27

extern const char YEAR_TO_DAY[];
extern const char YEAR_TO_MIN[];
extern const char YEAR_TO_SEC[];
extern const char YEAR_TO_USEC[];
//这个就是所谓的“模板”了,它使我们能够"看"到未知结构的内容。
typedef struct {
            INT4 type;
            INT4 len; // in byte
            const char *name;
            const char *format;
            INT4 offset;
            int bindtype; //default=0
} T_PkgType;

一个T_PkgType描述了结构中的一个成员,一个完整的结构由多个T_PkgType组成,如楼主的结构配一个模板:
T_PkgType xx_tpl[]={
        {CH_INT,sizeof(int),"a",NULL,-1},
        {CH_CLOB,-1,"b"},
     {CH_CLOB,-1,"c"},
        {-1,0,"xx",0}
};

几个问题都解决了,但是位置,变量的位置在哪?offset,没有?对,这不需要你写,你也写不出来。它在运行时计算出来。
作者: yulihua49    时间: 2011-11-19 22:03
本帖最后由 yulihua49 于 2011-11-19 22:09 编辑
的确,C在运行时(就不应该叫C了吧?机器码)是不知道任何结构的,只知道基地址+变址值。
就是 ...
yulihua49 发表于 2011-11-19 21:02



    我们来看一个例子,楼主的。
  1. cat xx.c
  2. #include <pack.h>
  3. #include <json_pack.h>

  4. T_PkgType xx_tpl[]={
  5.         {CH_INT,sizeof(int),"a",NULL,-1},
  6.         {CH_CLOB,-1,"b"},
  7.         {CH_CLOB,-1,"c"},
  8.         {-1,0,"xx",0}
  9. };

  10. typedef struct {
  11.         int a;
  12.         char *b;
  13.         char *c;
  14. } xx_stu;

  15. int main()
  16. {
  17. xx_stu xx;
  18. JSON_OBJECT json=json_object_new_object();

  19.         xx.a=123456;
  20.         xx.b="abcd";
  21.         xx.c="ABCD";

  22.         struct_to_json(json,&xx,xx_tpl,NULL);
  23.         printf("xx's json=xx:%s\n",
  24.                 json_object_to_json_string(json));
  25.         json_object_put(json);
  26.         return 0;
  27. }
  28. makefile:
  29. CFLAGS= -I$(SDBCDIR)/include
  30. LFLAGS= -L$(SDBCDIR)/lib

  31. xx:xx.o
  32.         cc -o xx xx.o $(LFLAGS) -lstr -ljson -lm -lpthread
  33. make
  34. cc -I/workspace/project/ticket-query/02-src/train-lines/sdbc/include   -c -o xx.o xx.c
  35. cc -o xx xx.o -L/workspace/project/ticket-query/02-src/train-lines/sdbc/lib -lstr -ljson -lm -lpthread
  36. tjs@linux:~/src> ./xx
  37. xx's json=xx:{ "a": "123456", "b": "abcd", "c": "ABCD" }

复制代码
那个struct_to_json是如何实现的?
作者: yulihua49    时间: 2011-11-19 22:40
回复  yulihua49


   我的难点在于
用C怎么得到一个结构的名称

比如
struct test
{
int a;
ch ...
keytounix 发表于 2011-11-19 16:43
  1. vi xx.c
  2. #include <pack.h>
  3. #include <json_pack.h>

  4. T_PkgType xx_tpl[]={
  5.         {CH_INT,sizeof(int),"a",NULL,-1},
  6.         {CH_CLOB,-1,"b"},
  7.         {CH_CLOB,-1,"c"},
  8.         {-1,0,"xx",0}
  9. };

  10. typedef struct {
  11.         int a;
  12.         char *b;
  13.         char *c;
  14. } xx_stu;

  15. int main()
  16. {
  17. xx_stu xx;
  18. JSON_OBJECT json=json_object_new_object();
  19. T_PkgType *tp;

  20.         xx.a=123456;
  21.         xx.b="abcd";
  22.         xx.c="ABCD";

  23.         struct_to_json(json,&xx,xx_tpl,NULL);
  24.         printf("xx:%s\n",
  25.                 json_object_to_json_string(json));
  26.         json_object_put(json);
  27.         for(tp=xx_tpl;tp->type>-1;tp++)
  28.                 printf("%s offset=%d,",tp->name,tp->offset);
  29.         printf("\nsizeof xx=%d\n",tp->offset);
  30.         return 0;
  31. }
  32. "xx.c" 35L, 617C 已写入                                                
  33. tjs@linux:~/src> make xx
  34. cc -I/workspace/project/ticket-query/02-src/train-lines/sdbc/include   -c -o xx.o xx.c
  35. cc -o xx xx.o -L/workspace/project/ticket-query/02-src/train-lines/sdbc/lib -lstr -ljson -lm -lpthread
  36. tjs@linux:~/src> ./xx
  37. xx:{ "a": "123456", "b": "abcd", "c": "ABCD" }
  38. a offset=0,b offset=4,c offset=8,
  39. sizeof xx=12
复制代码

作者: yulihua49    时间: 2011-11-19 22:44
本帖最后由 yulihua49 于 2011-11-19 22:50 编辑
yulihua49 发表于 2011-11-19 22:40



    把结构改一下,a改为short,看看模板里的offset:
它会按照编译器的规则计算offset,不需要也不允许做#pragma pack
  1. cat xx.c
  2. #include <pack.h>
  3. #include <json_pack.h>

  4. T_PkgType xx_tpl[]={
  5.         {CH_SHORT,sizeof(short),"a",NULL,-1},
  6.         {CH_CLOB,-1,"b"},
  7.         {CH_CLOB,-1,"c"},
  8.         {-1,0,"xx",0}
  9. };

  10. typedef struct {
  11.         short a;
  12.         char *b;
  13.         char *c;
  14. } xx_stu;

  15. int main()
  16. {
  17. xx_stu xx;
  18. JSON_OBJECT json=json_object_new_object();
  19. T_PkgType *tp;

  20.         xx.a=1234;
  21.         xx.b="abcd";
  22.         xx.c="ABCD";

  23.         struct_to_json(json,&xx,xx_tpl,NULL);
  24.         printf("xx:%s\n",
  25.                 json_object_to_json_string(json));
  26.         json_object_put(json);
  27.         for(tp=xx_tpl;tp->type>-1;tp++)
  28.                 printf("%s offset=%d,",tp->name,tp->offset);
  29.         printf("\nsizeof xx=%d\n",tp->offset);
  30.         return 0;
  31. }
  32. tjs@linux:~/src> make
  33. cc -I/workspace/project/ticket-query/02-src/train-lines/sdbc/include   -c -o xx.o xx.c
  34. cc -o xx xx.o -L/workspace/project/ticket-query/02-src/train-lines/sdbc/lib -lstr -ljson -lm -lpthread
  35. tjs@linux:~/src> ./xx
  36. xx:{ "a": "1234", "b": "abcd", "c": "ABCD" }
  37. a offset=0,b offset=4,c offset=8,
  38. sizeof xx=12
复制代码

作者: keytounix    时间: 2011-11-20 00:12
本帖最后由 keytounix 于 2011-11-20 00:31 编辑

回复 19# yulihua49

佩服!

你这个方法确实很巧!

也很好!

看完后我 有点启发

你是通过构造一个模版

但是还是需要通过一个"模版"

既然这样,

为什么不在结构体本身下功夫?

LZ的结构体信息
typedef struct {

        short a;

        char *b;

        char *c;

} xx_stu_t;

#define short_t 1
#define char_p_t 2
.....
现在我们构建一个新的结构体
#define JSON_STRUCT_FLAG "json"
typedef JSON_STRUCT
{
char * json_struct_FLAG;
char * seg_size;//用动态内存依次存放xx_stu_t中的数据类型;
char * seg_name;用动态内存molloc依次存放xxx_stu中的段名称
xx_stu_t stu;
} J_xx_stu_t;

比如LZ的结构体信息
可以打包成JSONstruct他、如下

J_xx_stu_t j_stu;


j_stu.json_struct_FLAG<-  JSON_STRUCT_FLAG



j_stu.seg_size=malloc(10);

j_stu.seg_size[0]=short_t;
j_stu.seg_size[1]=char_p_t;
j_stu.seg_size[2]=char_p_t;

j_stu.seg_name<- "a,b,c"


struct_to_json(JSON * json,void * json_struct);

这个相比你那个来说有一个优点就是
模版都不要了
也就是说适合所有的按照JSON_STRUCT 结构这种格式封装的结构体
你那个只适合按照你那个模版构造的结构体
但是缺点也是很明显的
就是
1.
json_struct这个东西封装了 数据类型和 结构体成员名称,
这个增加了额外的额外的空间,
如果处理大批量数据,
这个就有点悬了

2.
存在偏移量计算的问题,
因为编译器优化的时候,
可能会把结构体打乱,
__attribute__(pakged)能处理这个问题?

你的那个是否也会存在这个问题?
作者: keytounix    时间: 2011-11-20 00:40
本帖最后由 keytounix 于 2011-11-20 09:11 编辑

回复 21# yulihua49


    写了上面这个,我又想起另外一种方式,这个是我觉得最安全最可靠的
想的有点仓促,写出来可能会有很多错误,欢迎指正


typedef struct {

        short no;

        char *name;

        char * class;

} xx_stu_t;

xx_stu_t stu_t{100,"li4","class 4"}
这个结构体改造

typedef struct {

int32 num_of_seg;//存放字段的总数      
char * *seg_1;//不管他叫什么名称,反正我们在调用他时不需要,只需要偏移量

............

} J_stu_t __attribute__(pakged);


在a.c中
初始化LZ这个结构体如下


J_stu_t j_stu;
j_stu.num=3;

*j_stu.name<---"name:li4"
*j_stu.class<---"class:class 4"
......

注意这个
因为都是char **类型和
int32型
那么数据将是很对齐的东西

这意味着在这个结构体 存储的东西将是如下结构
&jst地址开始信息如下
&jst:        3
&jst+4:   addr1
&jst+8:   addr2
&jst+12:  addr3


---------------
addr1:  "no,100"
addr2:  "name,li4"
addr3:  "class,class 4"

这样岂不是很好?

在b.c中,我们不需要知道J_STU_t的具体内容
只需要知道一个事实就是


J_STU_t第一个4字节单元存放的是元素的个数
以后的都是指针


在struct_to_json()函数中

int struct_to_json(JSON * json,J_STU_t * jst)
{
int num;
memcpy(&num,jst,4)
//这个就获得了元素的数目
#define N 100
char buf[N]


#define  get_seg(seg_index,buf) \
do{                                              \
      memset(buf,0x00,N);            \
      memcpy(buf,*(jst + seg_index* 4),strlen(*(jst + seg_index* 4));\
}while(0);

}

for i<-  [1,num]
get_seg(i,buf);
func(json,buf);
end for

}

如此不是很好吗?



这个 方法的优点很明显

就是不会出现因为编译器优化造成的偏移量 计算错误的问题

为什么?
因为都是以4字节递增的
int  char ** 都是4字节
这个是非常安全的,
编译器优化或者不优化,都不会出现问题

另外缺点
可能体现在内存上

首先,结构体的开销可能不变
为什么?
虽然结构体中增加了一个int变量,
但是考虑到对齐问题,这个可能是一样的

当然上面给出的结构体 是不能体现这个结论的

其次,存储字段存放的额外开销
也就是每个字段 增加了  strlen(seg_name)+ 1个冒号这个开销
粗略估算 大概每一个字段增加9+1=10个字节左右


这些是需要考虑的
作者: yulihua49    时间: 2011-11-21 12:29
本帖最后由 yulihua49 于 2011-11-21 12:51 编辑
回复  yulihua49

2.
存在偏移量计算的问题,
因为编译器优化的时候,
可能会把结构体打乱,
__attribute__(pakged)能处理这个问题?

你的那个是否也会存在这个问题?keytounix 发表于 2011-11-20 00:12


结构布局不允许优化,也不允许pack。
十几年来,在很多应用环境和测试环境使用,没有发现哪个编译器优化布局。

看看你的方案,也很有意思,你不妨试试。
你这个可以叫“混合模板”方式,把模板和数据放在一起。这与C++反射技术类似,有人做了C++反射类,就像JAVA一样,能够找到对象里的变量、值、属性,可以序列化和反序列化。

不过还得探讨一下:
每个数据增加的空间不是问题。有时在数据库里,许多表同构,我用一个模板就可以了。
在多个模块中,模板可以共享,偏移量计算一次就可以了,在多线程中也是。

处理批量数据,我用一个结构数组就可以了,容易组织。
还有,很多时候只需要模板而不需要显式的结构,就是隐式结构。

如果人家已经定义了许多结构,你给配模板就行了,不用大规模修改原软件。
最后,我的模板可以通过数据库的表结构自动生成,可以用元数据库生成结构和模板。
作者: yulihua49    时间: 2011-11-21 12:40
本帖最后由 yulihua49 于 2011-11-21 15:55 编辑
回复  yulihua49

int num;
memcpy(&num,jst,4)
keytounix 发表于 2011-11-20 00:40


int num;
memcpy(&num,jst,4)
这个可不行。不过你的意思我明白。

数据里所有成员都用指针,管理起来太复杂。好像JSON对象也是这么做的,见json-c-0.9。
你要写很多函数协助工作,如按名存取数据(bean),按索引存取数据等等。那些内存如何管理?不要违例或泄漏了。
还不如用protobuf呢,属于特定对象一类。
坛子里有一哥们要做protobuf的ORM呢。这可能超出了楼主的需求,但是符合更一般的需求。

为了解决数据集合在运行时解析(运行时访问其内容)的问题,大家真是想了不少办法,但是面对原生态的结构的办法不多。

我的独立模板面对的是普通的原生态的结构,也是要进行SRM(Struct Relational Mapping)的,就像JAVA的Hibernate一样。
作者: yulihua49    时间: 2011-12-05 21:47
回复  yulihua49


    写了上面这个,我又想起另外一种方式,这个是我觉得最安全最可靠的
想的有点仓 ...
keytounix 发表于 2011-11-20 00:40


http://space.itpub.net/8804348/viewspace-478471#xspace-itemreply
作者: keytounix    时间: 2011-12-06 16:42
回复 26# yulihua49


    一旦扯上数据库就有点晕乎
  我打过交道的只有sqlite
作者: yulihua49    时间: 2011-12-07 16:09
本帖最后由 yulihua49 于 2011-12-07 16:41 编辑
回复  yulihua49


    一旦扯上数据库就有点晕乎
  我打过交道的只有sqlite
keytounix 发表于 2011-12-06 16:42



    也没什么。
就是数据库里有表,表结构与C结构可以有一个对应关系。扩展到多表,或一个复杂的SQL语句,也能找到与之对应的C结构。
寻找对应的结构比较复杂,但是之后有了结构和模板,处理起来就简单了。
用我的办法比较简单,你的办法就困难一些。
比如:ORACLE
  1. drop table UNIKEY_TEST ;
  2. create table UNIKEY_TEST (
  3.         ID              number(8)       not null,       --存款ID,包括币种,类别,存期等等
  4.         BEG_DATE        date            not null,       -- 开始日期
  5.         RATE            number(8,2),                    --利率
  6.         FLAG            number(1),                      -- 0:可用,-1:不可用
  7.         NOTE            varchar2(120)                   -- 备注
  8. );
  9. create unique index idex on UNIKEY_TEST(ID,BEG_DATE desc);
复制代码
> mkpatt.sh
输入表名: UNIKEY_TEST

T_PkgType UNIKEY_TEST_tpl[]={
        {CH_INT,sizeof(int),"id",0,-1},
        {CH_JUL,sizeof(INT4),"beg_date",YEAR_TO_DAY},
        {CH_DOUBLE,sizeof(double),"rate","%10.2lf"},
        {CH_TINY,1,"flag"},
        {CH_CHAR,121,"note"},
        {-1,0,"UNIKEY_TEST","id|beg_date|"}          //表名和主键
};

extern T_PkgType UNIKEY_TEST_tpl[];
typedef struct {
        int id;
        INT4 beg_date;
        double rate;
        char flag;
        char note[121];
} UNIKEY_TEST_stu;

你看看那个模板,是不是很容易构建select语句?

SELECT 提取各列名 FROM 提取表名 WHERE 由主键构建主键表达式 
prepare之
然后绑定变量到结构,每个列的绑定位置就是结构的基地址+模板的偏移量。
Fetch一下,数据库里的数据就跑到结构里去了。
作者: keytounix    时间: 2011-12-07 16:31
本帖最后由 keytounix 于 2011-12-07 16:33 编辑

回复 28# yulihua49


    我认真看了你给的那个连接

   数据库里面大批量的数据操作

  采用你的这个 模版方法 大概是最好的了, 最利于维护的了

  我那个方法还是没有跳出C的局限

  也许认真学习一下数据库和java对开拓视野有很大的好处
作者: yulihua49    时间: 2011-12-07 16:37
本帖最后由 yulihua49 于 2011-12-07 16:44 编辑
回复  yulihua49


    我认真看了你给的那个连接

   数据库里面大批量的数据操作

  采用你的这个 ...
keytounix 发表于 2011-12-07 16:31



    用了很多年了,现在有很大的改进,弄的和Hibernate差不多了。

咱们没走题吧?

映射程序都是用结构的基地址+模板里的偏移量,根据类型和格式处理数据。

最新的程序可以在QQ群 SDBC的群共享下载,源码和文档。
作者: keytounix    时间: 2011-12-07 16:47
回复 30# yulihua49


    没走题
  还是结构体的问题
呵呵
作者: yulihua49    时间: 2011-12-07 16:52
本帖最后由 yulihua49 于 2011-12-07 16:55 编辑
回复  yulihua49


    没走题
  还是结构体的问题
呵呵
keytounix 发表于 2011-12-07 16:47



    经常会有这个问题,貌似简单,其实水很深。
如:如何在文件里存结构的内容?
如何打印结构的内容?
如何在网上传输结构?等等。

楼主好像被吓跑了。
作者: ecloud    时间: 2011-12-12 22:51
经常会有这个问题,貌似简单,其实水很深。
如:如何在文件里存结构的内容?
如何打印结构的内 ...
yulihua49 发表于 2011-12-07 16:52



    这不就是Java对象序列化么?
    当然你偏要用C的结构体去折腾这些东西自然"水很深",就像我常说,哥用Basic一样能OO,当然是玩玩,不是用来干活的
实际工作,还是选择何时的工具为好
作者: 三月廿七    时间: 2011-12-12 22:57
哥用c 一样能oo, 而且就是用来干活的,
c 就是最合适的称手的工具
作者: 三月廿七    时间: 2011-12-12 23:04
哥用电子都可以oo, 只是我不想去oo
作者: yulihua49    时间: 2011-12-14 12:26
本帖最后由 yulihua49 于 2011-12-14 12:40 编辑
这不就是Java对象序列化么?
    当然你偏要用C的结构体去折腾这些东西自然"水很深",就像我常说 ...
ecloud 发表于 2011-12-12 22:51



    应该是JAVA的反射吧,C不能反射,只好映射。
不是玩一玩,是真正的高密集度的OLTP应用,生产用的。
无需OO,但还是借助一些OO的思想,进行模块封装,构造函数:XXXX_init,析构函数XXXX_free,
访问函数 setXxxxxx(),getXxxxx(),等等。
当然也不是现在折腾的,都折腾十几年了,
也不是没事折腾着玩,而是出于软件生产的需要,
真正是作为软件生产工具的。

这个东西水比较深,也是多年来摸着石头淌出来的,一点点发展出来的,
当年也是与楼主一样,不断提出问题,提出很幼稚的问题,一点点解决的,没有因为水深而止步。
当年搞这个东西的时候,JAVA才刚刚发明。




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2