設(shè)計一個可以存放任何類型變量,可存放大小運行時確定的類似數(shù)組的變量類型-------學(xué)習(xí)c++編程思想
Lib.h定義了一些數(shù)據(jù)類型和操作函數(shù)的聲明
/*****************************\
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這些操作函數(shù)的定義
/*****************************\
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編譯結(jié)果
---------- c編譯 ----------
In file included from Lib.c:4,
                 from LibTest.c:4:
Lib.h:20:39: warning: no newline at end of file     //這個沒關(guān)系
In file included from LibTest.c:4:
Lib.c:52:2: warning: no newline at end of file  //一樣沒關(guān)系
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

運行結(jié)果時:顯示
fetch(&intStash,0)=0
停止,調(diào)試窗口跳出

---------------------------------------------------------------------------
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*'   //類型強制轉(zhuǎn)換問題
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
-----------------------------------------------------------------------
誰能告訴我發(fā)生什么了?

相關(guān)知識:http://bbs.ccw.com.cn/viewthread.php?tid=104788
2.2 一個袖珍C庫

   【C函數(shù)庫的數(shù)據(jù)封裝方式】

     . struct        用于處理一組特性
     . C庫        一組struct + 一組活動在這些struct上的函數(shù)

   【一個變長數(shù)組模擬的例子】

     . 涉及操作:
       - 使用一個結(jié)構(gòu)保存數(shù)據(jù), 附加一組操作維護數(shù)據(jù)
       - C對于內(nèi)存的分配和使用

       - C的內(nèi)存分配(局部)函數(shù)
                函數(shù)名稱                用途
                -----------------------------------------------------------------------------
                _alloca                從數(shù)據(jù)棧分配內(nèi)存
               
                calloc                為數(shù)組分配緩存, 初始化每一個字節(jié)為0
                _calloc_dbg        調(diào)試版本下的 calloc

                _expand                在不移動的前提下擴展縮小內(nèi)存
                _expand_dbg        調(diào)試版本下的 _expand
               
                free                釋放內(nèi)存
                _free_dbg                調(diào)試版本下的 _free

                _get_sbh_threshold        返回申請上限

                _heapadd                添加內(nèi)存到堆
                _heapchk                檢測堆的連續(xù)性
                _heapmin                釋放堆中的空閑內(nèi)存
                _heapset                使用指定值填充堆內(nèi)存入口
                _heapwalk                返回堆中的每一個入口的信息

                malloc                從堆分配內(nèi)存
                _malloc_dbg        調(diào)試版本下的 malloc

                _msize                返回申請內(nèi)存塊的大小
                _msize_dbg        調(diào)試版本下的 _msize

                _query_new_handler        返回當前子函數(shù)句柄的地址, 子函數(shù)由 _set_new_handler 設(shè)置
                _query_new_mode        _set_new_mode 的句柄模式

                realloc                重新申請內(nèi)存塊新的大小
                _realloc_dbg        調(diào)試版本下的 realloc

                _set_new_handler        使得錯誤處理機制在 new 操作失敗的時候使能并且使能 STL 庫
                _set_new_mode        設(shè)置 malloc 的新的句柄模式
                _set_sbh_threshold        設(shè)置內(nèi)存分配上限

 ==> 客戶端應(yīng)用程序
        1) void* 的含義
           通過類型轉(zhuǎn)換, void* 可以轉(zhuǎn)換任何標準數(shù)據(jù)類型, 由此該變長數(shù)組可以不拘一格的支持相應(yīng)的數(shù)據(jù)類型, 只是類型檢查和轉(zhuǎn)換的工作由客戶端支持

〖個人理解〗

  這里用到一個一些C里面的如何建立函數(shù)庫, 使用函數(shù)庫和相應(yīng)的內(nèi)存以及建庫的常用技巧. 特別是內(nèi)存管理, 有了一個堆的概念. 堆用于申請一個連續(xù)內(nèi)存, 然后提供應(yīng)用程序的動態(tài)內(nèi)存分配函數(shù)申請堆內(nèi)的內(nèi)存, 同時應(yīng)用程序需要維護堆內(nèi)部的內(nèi)存管理.

  在C++特別是VC里面, 傳統(tǒng)的內(nèi)存分配函數(shù)已經(jīng)為new/delete代替, 而且也無需先申請一個堆. 不過如果開發(fā)COM還是會發(fā)現(xiàn)一些傳統(tǒng)內(nèi)存分配函數(shù)的影子, 畢竟從兼容性考慮, 2#標準的COM還是需要偏向或者生成C兼容的中間產(chǎn)物或者結(jié)果的.
----------------------------------

可是我的問題在哪里呢?我不需要導(dǎo)出dll,那么我的問題就時類型轉(zhuǎn)換的問題,資料說”只是類型檢查和轉(zhuǎn)換的工作由客戶端支持
“,這個客戶端支持指什么呢?為什么c編譯器通過了卻不能運行,而g++提示類型轉(zhuǎn)換錯誤

強制類型轉(zhuǎn)換更改
unsigned char*v=(unsigned char*)realloc(S->storage,(S->quantity+increase)*S->size);

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

后,編譯連接均通過,但是運行不顯示任何,彈出調(diào)試窗口要求調(diào)試
c++就沒那么麻煩,一次就編譯通過了,顯示結(jié)果如下
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
請按任意鍵繼續(xù). . .