A tiny C-like library(类C语言的库) (2)

The  storage pointer is an unsigned char* . An unsigned char  is the
这里对内存的指针是一个unsigned char*类型的,尽管在某些机器上,这个unsigned char类型的大小与其

最大表示相同,不过大多情况下它是C语言
smallest piece of storage a C compiler supports, although on some
编译器所能支持的最小存储单元。
machines it can be the same size as the largest. It's implementation
这个unsigned char类型的变量是与实现相独立的,不过经常只有一个字节长。
dependent, but is often one byte long. You might think that because
 你可能会觉得由于CStash是为了存储任意类型的变量而设计的,用“void*”
the CStash  is designed to hold any type of variable, a void*  would
这样的返回类型会很合适。
be more appropriate here. However, the purpose is not to treat this
不过,此处的目地并不是为了将这小块内存区域视为存储一未知类型变量
storage as a block of some unknown type, but rather as a block of
而是将之视为用来存储一连续的字节。
contiguous bytes.
The source code for the implementation file (which you may not
以上述原理为蓝本的源文件(这样的源文件在一些买来的C库中是找不到的)如下:
get if you buy a library commercially --you might get only a
compiled obj or lib  or dll, etc.) looks like this:

//: C04:CLib.cpp {O}
// Implementation of example C-like library
// Declare structure and functions:
#include "CLib.h"
#include <iostream>
#include <cassert> 
using namespace std;

// Quantity of elements to add
// when increasing storage:
const int increment = 100;
 
void initialize(CStash* s, int sz) { (从对结构体的指针定义到在函数中对结构体指针的应用就有了

类的萌芽,再在C++中把对结构体操作的函数定义到结构体中就有了类的出现,真是绝呀,就像世界杯冠军

从小组赛开始一路一步一个脚印的走过,给人的感觉特充实。)
  s->size = sz;
  s->quantity = 0;
  s->storage = 0;
  s->next = 0;
} (这也是构造函数的雏形!!!!)
 
int add(CStash* s, const void* element) {
  if(s->next >= s->quantity) //Enough space left?
    inflate(s, increment);
  // Copy element into storage,
  // starting at next empty space:
  int startBytes = s->next * s->size;
  unsigned char* e = (unsigned char*)element;
  for(int i = 0; i < s->size; i++)
    s->storage[startBytes + i] = e[i];
  s->next++;
  return(s->next - 1); // Index number
}
 
void* fetch(CStash* s, int index) {
  // Check index boundaries:
  assert(0 <= index);
  if(index >= s->next)
    return 0; // To indicate the end
  // Produce pointer to desired element:
  return &(s->storage[index * s->size]);
}
 
int count(CStash* s) {
  return s->next;  // Elements in CStash
}
 
void inflate(CStash* s, int increase) {
  assert(increase > 0);
  int newQuantity = s->quantity + increase;
  int newBytes = newQuantity * s->size;
  int oldBytes = s->quantity * s->size;
  unsigned char* b = new unsigned char[newBytes];
  for(int i = 0; i < oldBytes; i++)
    b[i] = s->storage[i]; // Copy old to new
  delete [](s->storage); // Old storage
  s->storage = b; // Point to new memory
  s->quantity = newQuantity;
}
 
void cleanup(CStash* s) {
  if(s->storage != 0) {
   cout << "freeing storage" << endl;
   delete []s->storage;
  }
} ///:~


 initialize( ) performs the necessary setup for struct CStash  by
setting the internal variables to appropriate values. Initially, the
initialize()方法的作用是对结构体CStash以对内部变量设置合适值的方式进行必要的初始化。
storage pointer is set to zero —— no initial storage is allocated.
起始时,这个storage指针设置为零——即没对对内存区的分配。
The  add( ) function inserts an element into the CStash at the next
add()方法的作用是将一个新的元素插到next指定的位置。
available location. First, it checks to see if there is any available
当然,在用add()时,它将首先检查看看在此结构体中是否还剩有可用的存储空间
space left. If not, it expands the storage using the inflate( )  function,
要是没有的话,将再调用inflate()方法(此方法我们随后将会讨论到)来扩展此storage
described later.
结构体的内存区。
Because the compiler doesn't know the specific type of the variable
由于编译器无法知道存储变量的类型(因为所有方法的返回值都是void*型)
being stored (all the function gets is a void*), you can't just do an
我们也就不能在此对其进行赋值了,
assignment, which would certainly be the convenient thing.
 而此赋值操作在别的情况下本来应该会很方便的。
Instead, you must copy the variable byte-by-byte. The most
相反,在此,你必须得一个字节一个字节的将变量拷贝过来。
straightforward way to perform the copying is with array indexing.
在进行拷贝中最容易想到的方法就是用数组的索引来进行。
Typically, there are already data bytes in storage, and this is
通常情况下,在storage中已有数据存在,这可以通过next值反映出来。
indicated by the value of next. To start with the right byte offset,
为了以恰当的字节偏移量开始,将对next乘以每一个元素的字节数来得到startBytes
next is multiplied by the size of each element (in bytes) to produce
startBytes. Then the argument element is cast to an unsigned char*
随后,参数element将被转为unsigned char型,这样它才能以逐个字节的形式被访问
so that it can be addressed byte-by-byte and copied into the
并将其所包含的元素拷贝到storage的可用空间中。
available storage  space. next is incremented so that it indicates the
在此过程中,next的值将会随着增加以便来表达出storage中下一个可用空间。
next available piece of storage, and the “index number”where the
在此过程中,“next number”也同样会随着增加,因为fetch()方法会用
value was stored so that value can be retrieved using this index
此值来取出对应的存储元素。
number with fetch( ).


fetch( ) checks to see that the index isn't out of bounds and then
调用fetch()方法时,将会对index进行检验看其是否已越界,在没有越界时,
returns the address of the desired variable, calculated using the
此方法会返回目标元素的地址(此地址是由index参数计算而来)
index argument. Since index indicates the number of elements to
由于index表达了在storage中元素的偏移量,
offset into the storage, it must be multiplied by the number of bytes
它必须乘以单个元素所占内存空间大小的值来得到真实偏移量。
occupied by each piece to produce the numerical offset in bytes.
When this offset is used to index into storage  using array indexing,
在用偏移量传值到storage时,你并不能得到此所对应的地址,而是得到此地址处的
you don't get the address, but instead the byte at the address. To
字节值。为了得到此地址,你必须得用取值操作符&.
produce the address, you must use the address-of operator &. 


 count() may look a bit strange at first to a seasoned C programmer.
刚开始时,对那些并不常用C语言的程序员来说,count()方法可能看起来有些别扭。
It seems like a lot of trouble to go through to do something that
 可能会有这样的感觉,就是用这个方法会比手动的处理更烦事些。
would probably be a lot easier to do by hand. If you have a struct
 例如,你有个名为intStash的结构体,对其直接采用intStash.next方法
 CStash called intStash, for example, it would seem much more
来找出指定元素将比调用count函数更直接些的。
straightforward to find out how many elements it has by saying
intStash.next instead of making a function call (which has
overhead), such as count(&intStash). However, if you wanted to
不过,要是你想改变CStash内部的代表值并也随之改变count的计算方式,
change the internal representation of CStash and thus the way the
count was calculated, the function call interface allows the
调用count()函数将更快捷些。
necessary flexibility. But alas, most programmers won't bother to
然而,大多数的程序员也不会费事地在你提供的C库中查找以找到一个更佳的设计的。
find out about your “better” design for the library. They'll look
 他们会找到struct并直接用next的值,还更有可能在你并不允许的情况下更改next的值。
the struct and grab the next value directly, and possibly even
change next without your permission. If only there were some way
for the library designer to have better control over things like this!
要是库函数设计的程序员有一些更好的方法来对类似这样的事进行有效的控制就好了。
(Yes, that's foreshadowing.)(不错,这仅仅是一个预想。) 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值