设计一个可以存放任何类型变量,可存放大小运行时确定的类似数组的变量类型-------学习c++编程思想
Lib.h定义了一些数据类型和操作函数的声明
/*****************************\
example c library
page24 in Thinking in c++
array like creat at runtime
\****************************
*/


typedef 
struct STASHtag
{
    
int size;                    //size of each space
    int quantity;              //number of storage
    int next;                   //next empty space
    unsigned char*storage;  //dynamically allocated array of bytes
}
Stash;
   
   
void initialize(Stash*S,int Size);
   
void cleanup(Stash*S);
   
int add(Stash*S,char*element);
   
void* fetch(Stash*S,int index);
   
int count(Stash*S);
   
void inflate(Stash*S,int increase);

Lib.c这些操作函数的定义
/*****************************\
implementation of example c library
\****************************
*/

#include
"Lib.h"
#include
<assert.h>
#include
<stdlib.h>
#include
<string.h>
#include
<stdio.h>
void initialize(Stash*S,int Size)   //initial
{
    S
->size=Size;
    S
->quantity=0;
    S
->storage=0;
    S
->next=0;
}


void cleanup(Stash*S)
{
    
if(S->storage)
    
{
        puts(
"freeing storage");
        free(S
->storage);
    }

}


int add(Stash*S,char*element)      //add a element
{
    
if(S->next>=S->quantity)
        inflate(S,
100);
    memcpy(
&(S->storage[S->next*S->size]),element,S->size);
    S
->next++;
    
return(S->next-1);
}


void*fetch(Stash*S,int index)      //get one of the elements
{
    
if(index>=S->next||index<0)return(0);
    
return &(S->storage[index*S->size]);
}


int count(Stash*S)
{
    
return S->next;
}


void inflate(Stash*S,int increase)    //creat new space when need
{
    unsigned 
char*v=realloc(S->storage,(S->quantity+increase)*S->size);
    assert(v);
    S
->storage=v;
    S
->quantity+=increase;
}

测试这个袖珍c库:LibTest.c
/****************************\
test the c library
\***************************
*/

#include 
"Lib.c"
#define BUFSIZE  80

int main(void)
{
    Stash intStash,stringStash;
    
int i;
    FILE
*file;
    
char buf[BUFSIZE];
    
char*cp;
    initialize(
&stringStash,sizeof(int));
    
for(i=0;i<100;i++)
        add(
&intStash,&i);
    initialize(
&stringStash,sizeof(char)*BUFSIZE);
    file
=fopen("LibTest.c","r");
    assert(file);
    
while(fgets(buf,BUFSIZE,file))
        add(
&stringStash,buf);
    fclose(file);
    
for(i=0;i<count(&intStash);i++)
        printf(
"fetch(&intStash,%d)=%d\n",i,*(int*)fetch(&intStash,i));
       
// printf("fetch(&intStash,%d)=%d\n",i,fetch(&intStash,i));
    i=0;
    
while((cp=fetch(&stringStash,i++))!=0)
        printf(
"fetch(&stringStash,%d)=%s",i-1,cp);
    putchar(
'\n');
    cleanup(
&intStash);
    cleanup(
&stringStash);
    system(
"pause");
    
return 0;
}

gcc编译结果
---------- c编译 ----------
In file included from Lib.c:4,
                 from LibTest.c:4:
Lib.h:20:39: warning: no newline at end of file     //这个没关系
In file included from LibTest.c:4:
Lib.c:52:2: warning: no newline at end of file  //一样没关系
LibTest.c: In function `main':
LibTest.c:8: warning: return type of 'main' is not `int'
LibTest.c:28:2: warning: no newline at end of file //一样

Output completed (1 sec consumed) - Normal Termination

运行结果时:显示
fetch(&intStash,0)=0
停止,调试窗口跳出

---------------------------------------------------------------------------
g++编译:
---------- cpp编译 ----------
In file included from Lib.c:4,
                 from LibTest.c:4:
Lib.h:20:39: warning: no newline at end of file
In file included from LibTest.c:4:
Lib.c: In function `void inflate(Stash*, int)':
Lib.c:48: error: invalid conversion from `void*' to `unsigned char*'   //类型强制转换问题
In file included from LibTest.c:4:
Lib.c:52:2: warning: no newline at end of file
LibTest.c: At global scope:
LibTest.c:8: error: `main' must return `int'  //不知道为什么?
LibTest.c: In function `int main(...)':
LibTest.c:23: error: invalid conversion from `void*' to `char*'//一样
LibTest.c:28:2: warning: no newline at end of file

Output completed (0 sec consumed) - Normal Termination
-----------------------------------------------------------------------
谁能告诉我发生什么了?

相关知识:http://bbs.ccw.com.cn/viewthread.php?tid=104788
2.2 一个袖珍C库

   【C函数库的数据封装方式】

     . struct        用于处理一组特性
     . C库        一组struct + 一组活动在这些struct上的函数

   【一个变长数组模拟的例子】

     . 涉及操作:
       - 使用一个结构保存数据, 附加一组操作维护数据
       - C对于内存的分配和使用

       - C的内存分配(局部)函数
                函数名称                用途
                -----------------------------------------------------------------------------
                _alloca                从数据栈分配内存
               
                calloc                为数组分配缓存, 初始化每一个字节为0
                _calloc_dbg        调试版本下的 calloc

                _expand                在不移动的前提下扩展缩小内存
                _expand_dbg        调试版本下的 _expand
               
                free                释放内存
                _free_dbg                调试版本下的 _free

                _get_sbh_threshold        返回申请上限

                _heapadd                添加内存到堆
                _heapchk                检测堆的连续性
                _heapmin                释放堆中的空闲内存
                _heapset                使用指定值填充堆内存入口
                _heapwalk                返回堆中的每一个入口的信息

                malloc                从堆分配内存
                _malloc_dbg        调试版本下的 malloc

                _msize                返回申请内存块的大小
                _msize_dbg        调试版本下的 _msize

                _query_new_handler        返回当前子函数句柄的地址, 子函数由 _set_new_handler 设置
                _query_new_mode        _set_new_mode 的句柄模式

                realloc                重新申请内存块新的大小
                _realloc_dbg        调试版本下的 realloc

                _set_new_handler        使得错误处理机制在 new 操作失败的时候使能并且使能 STL 库
                _set_new_mode        设置 malloc 的新的句柄模式
                _set_sbh_threshold        设置内存分配上限

 ==> 客户端应用程序
        1) void* 的含义
           通过类型转换, void* 可以转换任何标准数据类型, 由此该变长数组可以不拘一格的支持相应的数据类型, 只是类型检查和转换的工作由客户端支持

〖个人理解〗

  这里用到一个一些C里面的如何建立函数库, 使用函数库和相应的内存以及建库的常用技巧. 特别是内存管理, 有了一个堆的概念. 堆用于申请一个连续内存, 然后提供应用程序的动态内存分配函数申请堆内的内存, 同时应用程序需要维护堆内部的内存管理.

  在C++特别是VC里面, 传统的内存分配函数已经为new/delete代替, 而且也无需先申请一个堆. 不过如果开发COM还是会发现一些传统内存分配函数的影子, 毕竟从兼容性考虑, 2#标准的COM还是需要偏向或者生成C兼容的中间产物或者结果的.
----------------------------------

可是我的问题在哪里呢?我不需要导出dll,那么我的问题就时类型转换的问题,资料说”只是类型检查和转换的工作由客户端支持
“,这个客户端支持指什么呢?为什么c编译器通过了却不能运行,而g++提示类型转换错误

强制类型转换更改
unsigned char*v=(unsigned char*)realloc(S->storage,(S->quantity+increase)*S->size);

while((cp=(char*)fetch(&stringStash,i++))!=0)

后,编译连接均通过,但是运行不显示任何,弹出调试窗口要求调试
c++就没那么麻烦,一次就编译通过了,显示结果如下
intStash.fetch(0)=0
intStash.fetch(1)=1
intStash.fetch(2)=2
intStash.fetch(3)=3
intStash.fetch(4)=4
intStash.fetch(5)=5
intStash.fetch(6)=6
intStash.fetch(7)=7
intStash.fetch(8)=8
intStash.fetch(9)=9
intStash.fetch(10)=10
intStash.fetch(11)=11
intStash.fetch(12)=12
intStash.fetch(13)=13
intStash.fetch(14)=14
intStash.fetch(15)=15
intStash.fetch(16)=16
intStash.fetch(17)=17
intStash.fetch(18)=18
intStash.fetch(19)=19
intStash.fetch(20)=20
intStash.fetch(21)=21
intStash.fetch(22)=22
intStash.fetch(23)=23
intStash.fetch(24)=24
intStash.fetch(25)=25
intStash.fetch(26)=26
intStash.fetch(27)=27
intStash.fetch(28)=28
intStash.fetch(29)=29
intStash.fetch(30)=30
intStash.fetch(31)=31
intStash.fetch(32)=32
intStash.fetch(33)=33
intStash.fetch(34)=34
intStash.fetch(35)=35
intStash.fetch(36)=36
intStash.fetch(37)=37
intStash.fetch(38)=38
intStash.fetch(39)=39
intStash.fetch(40)=40
intStash.fetch(41)=41
intStash.fetch(42)=42
intStash.fetch(43)=43
intStash.fetch(44)=44
intStash.fetch(45)=45
intStash.fetch(46)=46
intStash.fetch(47)=47
intStash.fetch(48)=48
intStash.fetch(49)=49
intStash.fetch(50)=50
intStash.fetch(51)=51
intStash.fetch(52)=52
intStash.fetch(53)=53
intStash.fetch(54)=54
intStash.fetch(55)=55
intStash.fetch(56)=56
intStash.fetch(57)=57
intStash.fetch(58)=58
intStash.fetch(59)=59
intStash.fetch(60)=60
intStash.fetch(61)=61
intStash.fetch(62)=62
intStash.fetch(63)=63
intStash.fetch(64)=64
intStash.fetch(65)=65
intStash.fetch(66)=66
intStash.fetch(67)=67
intStash.fetch(68)=68
intStash.fetch(69)=69
intStash.fetch(70)=70
intStash.fetch(71)=71
intStash.fetch(72)=72
intStash.fetch(73)=73
intStash.fetch(74)=74
intStash.fetch(75)=75
intStash.fetch(76)=76
intStash.fetch(77)=77
intStash.fetch(78)=78
intStash.fetch(79)=79
intStash.fetch(80)=80
intStash.fetch(81)=81
intStash.fetch(82)=82
intStash.fetch(83)=83
intStash.fetch(84)=84
intStash.fetch(85)=85
intStash.fetch(86)=86
intStash.fetch(87)=87
intStash.fetch(88)=88
intStash.fetch(89)=89
intStash.fetch(90)=90
intStash.fetch(91)=91
intStash.fetch(92)=92
intStash.fetch(93)=93
intStash.fetch(94)=94
intStash.fetch(95)=95
intStash.fetch(96)=96
intStash.fetch(97)=97
intStash.fetch(98)=98
intStash.fetch(99)=99
stringStash.fetch(0)=//libtest.cpp--test of c++ library
stringStash.fetch(1)=#include<iostream>
stringStash.fetch(2)=#include"LIBCPP.H"
stringStash.fetch(3)=#include<stdio.h>
stringStash.fetch(4)=#include<assert.h>
stringStash.fetch(5)=#define BUFSIZE  80
stringStash.fetch(6)=int main()
stringStash.fetch(7)={
stringStash.fetch(8)=   stash intStash,stringStash;
stringStash.fetch(9)=   int i;
stringStash.fetch(10)=  FILE* file;
stringStash.fetch(11)=  char buf[BUFSIZE];
stringStash.fetch(12)=  char*cp;
stringStash.fetch(13)=  intStash.initialize(sizeof(int));
stringStash.fetch(14)=  for(i=0;i<100;i++)
stringStash.fetch(15)=          intStash.add(&i);
stringStash.fetch(16)=  stringStash.initialize(sizeof(char)*BUFSIZE);
stringStash.fetch(17)=  file=fopen("LIBTEST.CPP","r");
stringStash.fetch(18)=  assert(file);
stringStash.fetch(19)=  while(fgets(buf,BUFSIZE,file))
stringStash.fetch(20)=          stringStash.add(buf);
stringStash.fetch(21)=  fclose(file);
stringStash.fetch(22)=  for(i=0;i<intStash.count();i++)
stringStash.fetch(23)=          printf("intStash.fetch(%d)=%d\n",i,*(int*)intSta
sh.fetch(i));
stringStash.fetch(24)=  i=0;
stringStash.fetch(25)=  while((cp=(char*)stringStash.fetch(i++))!=0)
stringStash.fetch(26)=          printf("stringStash.fetch(%d)=%s",i-1,cp);
stringStash.fetch(27)=  putchar('\n');
stringStash.fetch(28)=    intStash.cleanup();
stringStash.fetch(29)=  stringStash.cleanup();
stringStash.fetch(30)=  system("pause");
stringStash.fetch(31)=  return 0;
stringStash.fetch(32)=}

freeing storage
freeing storage
请按任意键继续. . .