设计一个可以存放任何类型变量,可存放大小运行时确定的类似数组的变量类型-------学习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
请按任意键继续. . .