阿学的学习空间

学习博客

中国教师博客网 首页 新随笔 联系 聚合 登录
  22 Posts :: 2 Stories :: 5 Comments :: 0 Trackbacks

留言簿(6)

随笔分类

随笔档案

文章分类

文章档案

友情链接

搜索

最新评论

阅读排行榜

评论排行榜

2010年2月14日 #

atoi

  C语言库函数名: atoi
  功 能: 把字符串转换成整型数.
  名字来源:array to integer 的缩写.
  函数说明: atoi()会扫描参数nptr字符串,如果第一个字符不是数字也不是正负号返回零,否则开始做类型转换,之后检测到非数字或结束符 \0 时停止转换,返回整型数。
  原型: int atoi(const char *nptr);
  需要用到的头文件: #include <stdlib.h>
  程序例:
  1)
  #include <stdlib.h>
  #include <stdio.h>
  int main(void)
  {
  int n;
  char *str = "12345.67";
  n = atoi(str);
  printf("string = %s integer = %d\n", str, n);
  return 0;
  }
  执行结果
  string = 12345.67 integer = 12345
  2)
  #include <stdlib.h>
  #include <stdio.h>
  int main()
  {
  char a[] = "-100" ;
  char b[] = "123" ;
  int c ;
  c = atoi( a ) + atoi( b ) ;
  printf("c = %d\n", c) ;
  return 0;
  }
  执行结果
  c = 23
  简单的实现atoi函数的源代码:
  int my_atoi(const char *str){
  int result;
  int signal = 1; /* 默认为正数 */
  if((*str>='0'&&*str<='9')||*str=='-'||*str=='+'){
  if(*str=='-'||*str=='+'){
  if(*str=='-')
  signal = -1; /* 输入负数 */
  str++;
  }
  }
  else return 0;
  /* 开始转换 */
  while(*str>='0'&&*str<='9')
  result = result*10+(*str++ -'0');
  return signal*result;
  }
posted @ 2010-02-14 11:22 末名教师 阅读(12) | 评论 (0)编辑 收藏

malloc

  原型:extern void *malloc(unsigned int num_bytes);
  用法:#include <malloc.h>
  或#include<stdlib.h>
  功能:用于向内存申请空间,分配长度为num_bytes字节的内存块
  说明:如果分配成功则返回指向被分配内存的指针,否则返回空指针NULL。
  当内存不再使用时,应使用free()函数将内存块释放。
  调用格式,
  
指针名=(指针所指对象的数据类型*)malloc(个数*sizeof(指针所指对象的数据类型)),其对应例子如下:
  int *p = (int *) malloc ( n* sizeof(int) );
  举例
  // malloc.c
  #include <syslib.h>
  #include <malloc.h>
  main()
  {
  char *p;
  clrscr(); // clear screen
  p=(char *)malloc(100);
  if(p)
  printf("Memory Allocated at: %x",p);
  else
  printf("Not Enough Memory!\n");
  
  if(p)
  free(p);
  getchar();
  return 0;
  }
  

[编辑本段]
malloc()函数的工作机制

  malloc函数的实质体现在,它有一个将可用的内存块连接为一个长长的列表的所谓空闲链表。调用malloc函数时,它沿连接表寻找一个大到足以满足用户请求所需要的内存块。然后,将该内存块一分为二(一块的大小与用户请求的大小相等,另一块的大小就是剩下的字节)。接下来,将分配给用户的那块内存传给用户,并将剩下的那块(如果有的话)返回到连接表上。调用free函数时,它将用户释放的内存块连接到空闲链上。到最后,空闲链会被切成很多的小内存片段,如果这时用户申请一个大的内存片段,那么空闲链上可能没有可以满足用户要求的片段了。于是,malloc函数请求延时,并开始在空闲链上翻箱倒柜地检查各内存片段,对它们进行整理,将相邻的小空闲块合并成较大的内存块。

[编辑本段]
浅析malloc()的几种实现方式

  malloc()是C语言中动态存储管理的一组标准库函数之一。其作用是在内存的动态存储区中分配一个长度为size的连续空间。其参数是一个无符号整形数,返回值是一个指向所分配的连续存储域的起始地址的指针。
  动态内存分配就是指在程序执行的过程中动态地分配或者回收存储空间的分配内存的方法。动态内存分配不像数组等静态内存分配方法那样需要预先分配存储空间,而是由系统根据程序的需要即时分配,且分配的大小就是程序要求的大小。本文简单介绍动态内存分配函数malloc()及几种实现方法。
  1. 简介
  malloc()是C语言中动态存储管理的一组标准库函数之一。其作用是在内存的动态存储区中分配一个长度为size的连续空间。其参数是一个无符号整形数,返回值是一个指向所分配的连续存储域的起始地址的指针。还有一点必须注意的是,当函数未能成功分配存储空间(如内存不足)就会返回一个NULL指针。所以在调用该函数时应该检测返回值是否为NULL并执行相应的操作。
  2. 函数说明
  C语言的动态存储管理由一组标准库函数实现,其原型在标准文件<stdlib.h>里描述,需要用这些功能时应包含这个文件。与动态存储分配有关的函数共有四个,其中就包括存储分配函数malloc()。函数原型是:void *malloc (size_t n);这里的size_t是标准库里定义的一个类型,它是一个无符号整型。这个整型能够满足所有对存储块大小描述的需要,具体相当于哪个整型由具体的C系统确定。malloc的返回值为(void *)类型(这是通用指针的一个重要用途),它分配一片能存放大小为n的数据的存储块,返回对应的指针值;如果不能满足申请(找不到能满足要求的存储块)就返回NULL。在使用时,应该把malloc的返回值转换到特定指针类型,赋给一个指针。
  注意,虽然这里的存储块是通过动态分配得到的,但是它的大小也是确定的,同样不允许越界使用。例如上面程序段分配的块里能存n个双精度数据,随后的使用就必须在这个范围内进行。越界使用动态分配的存储块,尤其是越界赋值,可能引起非常严重的后果,通常会破坏程序的运行系统,可能造成本程序或者整个计算机系统垮台。
  下例是一个动态分配的例子:
  #include <stdio.h>
  #include<stdlib.h>
  main()
  {
  int count,*array; /*count是一个计数器,array是一个整型指针,也可以理解为指向一个整型数组的首地址*/
  count=100;
  if((array=(int *)malloc(10*sizeof(int))) == NULL)
  {
  printf("不能成功分配存储空间。");
  exit(1);
  }
  for(count=0;count<10;count++) /*给数组赋值*/
  array[count]=count;
  for(count=0;count<10;count++) /*打印数组元素*/
  printf("%2d",array[count]);
  }
  上例中动态分配了10个整型存储区域,然后进行赋值并打印。例中if((array=(int *) malloc (10*sizeof(int)))==NULL)语句可以分为以下几步:
  1)分配10个整型的连续存储空间,并返回一个指向其起始地址的整型指针
  2)把此整型指针地址赋给array
  3)检测返回值是否为NULL
  例2,本例用于说明malloc()的返回值的情况
  下面的代码片段的输出是什么,为什么?
  char *ptr;
  if ((ptr = (char *)malloc(0)) == NULL)
  puts("Got a null pointer");
  else
  puts("Got a valid pointer");
  把0值传给了函数malloc,得到了一个合法的指针之后,这就是上面的代码,该代码的输出是"Got a valid pointer"
  3. malloc()工作机制
  malloc函数的实质体现在,它有一个将可用的内存块连接为一个长长的列表的所谓空闲链表。调用malloc函数时,它沿连接表寻找一个大到足以满足用户请求所需要的内存块。然后,将该内存块一分为二(一块的大小与用户请求的大小相等,另一块的大小就是剩下的字节)。接下来,将分配给用户的那块内存传给用户,并将剩下的那块(如果有的话)返回到连接表上。调用free函数时,它将用户释放的内存块连接到空闲链上。到最后,空闲链会被切成很多的小内存片段,如果这时用户申请一个大的内存片段,那么空闲链上可能没有可以满足用户要求的片段了。于是,malloc函数请求延时,并开始在空闲链上翻箱倒柜地检查各内存片段,对它们进行整理,将相邻的小空闲块合并成较大的内存块。
  4. malloc()在操作系统中的实现
  在 C 程序中,多次使用malloc () 和 free()。不过,您可能没有用一些时间去思考它们在您的操作系统中是如何实现的。本节将向您展示 malloc 和 free 的一个最简化实现的代码,来帮助说明管理内存时都涉及到了哪些事情。
  在大部分操作系统中,内存分配由以下两个简单的函数来处理:
  void *malloc (long numbytes):该函数负责分配 numbytes 大小的内存,并返回指向第一个字节的指针。
  void free(void *firstbyte):如果给定一个由先前的 malloc 返回的指针,那么该函数会将分配的空间归还给进程的“空闲空间”。
  malloc_init 将是初始化内存分配程序的函数。它要完成以下三件事:将分配程序标识为已经初始化,找到系统中最后一个有效内存地址,然后建立起指向我们管理的内存的指针。这三个变量都是全局变量:
  清单 1. 我们的简单分配程序的全局变量
  int has_initialized = 0;
  void *managed_memory_start;
  void *last_valid_address;
  如前所述,被映射的内存的边界(最后一个有效地址)常被称为系统中断点或者 当前中断点。在很多 UNIX? 系统中,为了指出当前系统中断点,必须使用 sbrk(0) 函数。 sbrk 根据参数中给出的字节数移动当前系统中断点,然后返回新的系统中断点。使用参数 0 只是返回当前中断点。这里是我们的 malloc 初始化代码,它将找到当前中断点并初始化我们的变量:
  清单 2. 分配程序初始化函数
  /* Include the sbrk function */
  #include
  void malloc_init()
  {
  /* grab the last valid address from the OS */
  last_valid_address = sbrk(0);
  /* we don't have any memory to manage yet, so
  *just set the beginning to be last_valid_address
  */
  managed_memory_start = last_valid_address;
  /* Okay, we're initialized and ready to go */
  has_initialized = 1;
  }
  现在,为了完全地管理内存,我们需要能够追踪要分配和回收哪些内存。在对内存块进行了 free 调用之后,我们需要做的是诸如将它们标记为未被使用的等事情,并且,在调用 malloc 时,我们要能够定位未被使用的内存块。因此, malloc 返回的每块内存的起始处首先要有这个结构:
  清单 3. 内存控制块结构定义
  struct mem_control_block {
  int is_available;
  int size;
  };
  现在,您可能会认为当程序调用 malloc 时这会引发问题 —— 它们如何知道这个结构?答案是它们不必知道;在返回指针之前,我们会将其移动到这个结构之后,把它隐藏起来。这使得返回的指针指向没有用于任何其他用途的内存。那样,从调用程序的角度来看,它们所得到的全部是空闲的、开放的内存。然后,当通过 free() 将该指针传递回来时,我们只需要倒退几个内存字节就可以再次找到这个结构。
  在讨论分配内存之前,我们将先讨论释放,因为它更简单。为了释放内存,我们必须要做的惟一一件事情就是,获得我们给出的指针,回退 sizeof(struct mem_control_block) 个字节,并将其标记为可用的。这里是对应的代码:
  清单 4. 解除分配函数
  void free(void *firstbyte) {
  struct mem_control_block *mcb;
  /* Backup from the given pointer to find the
  * mem_control_block
  */
  mcb = firstbyte - sizeof(struct mem_control_block);
  /* Mark the block as being available */
  mcb->is_available = 1;
  /* That's It! We're done. */
  return;
  }
  如您所见,在这个分配程序中,内存的释放使用了一个非常简单的机制,在固定时间内完成内存释放。分配内存稍微困难一些。以下是该算法的略述:
  清单 5. 主分配程序的伪代码
  1. If our allocator has not been initialized, initialize it.
  2. Add sizeof(struct mem_control_block) to the size requested.
  3. start at managed_memory_start.
  4. Are we at last_valid address?
  5. If we are:
  A. We didn't find any existing space that was large enough
  -- ask the operating system for more and return that.
  6. Otherwise:
  A. Is the current space available (check is_available from
  the mem_control_block)?
  B. If it is:
  i) Is it large enough (check "size" from the
  mem_control_block)?
  ii) If so:
  a. Mark it as unavailable
  b. Move past mem_control_block and return the
  pointer
  iii) Otherwise:
  a. Move forward "size" bytes
  b. Go back go step 4
  C. Otherwise:
  i) Move forward "size" bytes
  ii) Go back to step 4
  我们主要使用连接的指针遍历内存来寻找开放的内存块。这里是代码:
  清单 6. 主分配程序
  void *malloc(long numbytes) {
  /* Holds where we are looking in memory */
  void *current_location;
  /* This is the same as current_location, but cast to a
  * memory_control_block
  */
  struct mem_control_block *current_location_mcb;
  /* This is the memory location we will return. It will
  * be set to 0 until we find something suitable
  */
  void *memory_location;
  /* Initialize if we haven't already done so */
  if(! has_initialized) {
  malloc_init();
  }
  /* The memory we search for has to include the memory
  * control block, but the users of malloc don't need
  * to know this, so we'll just add it in for them.
  */
  numbytes = numbytes + sizeof(struct mem_control_block);
  /* Set memory_location to 0 until we find a suitable
  * location
  */
  memory_location = 0;
  /* Begin searching at the start of managed memory */
  current_location = managed_memory_start;
  /* Keep going until we have searched all allocated space */
  while(current_location != last_valid_address)
  {
  /* current_location and current_location_mcb point
  * to the same address. However, current_location_mcb
  * is of the correct type, so we can use it as a struct.
  * current_location is a void pointer so we can use it
  * to calculate addresses.
  */
  current_location_mcb =
  (struct mem_control_block *)current_location;
  if(current_location_mcb->is_available)
  {
  if(current_location_mcb->size >= numbytes)
  {
  /* Woohoo! We've found an open,
  * appropriately-size location.
  */
  /* It is no longer available */
  current_location_mcb->is_available = 0;
  /* We own it */
  memory_location = current_location;
  /* Leave the loop */
  break;
  }
  }
  /* If we made it here, it's because the Current memory
  * block not suitable; move to the next one
  */
  current_location = current_location +
  current_location_mcb->size;
  }
  /* If we still don't have a valid location, we'll
  * have to ask the operating system for more memory
  */
  if(! memory_location)
  {
  /* Move the program break numbytes further */
  sbrk(numbytes);
  /* The new memory will be where the last valid
  * address left off
  */
  memory_location = last_valid_address;
  /* We'll move the last valid address forward
  * numbytes
  */
  last_valid_address = last_valid_address + numbytes;
  /* We need to initialize the mem_control_block */
  current_location_mcb = memory_location;
  current_location_mcb->is_available = 0;
  current_location_mcb->size = numbytes;
  }
  /* Now, no matter what (well, except for error conditions),
  * memory_location has the address of the memory, including
  * the mem_control_block
  */
  /* Move the pointer past the mem_control_block */
  memory_location = memory_location + sizeof(struct mem_control_block);
  /* Return the pointer */
  return memory_location;
  }
  这就是我们的内存管理器。现在,我们只需要构建它,并在程序中使用它即可。
  5. malloc()的其他实现
  malloc() 的实现有很多,这些实现各有优点与缺点。在设计一个分配程序时,要面临许多需要折衷的选择,其中包括:
  分配的速度。
  回收的速度。
  有线程的环境的行为。
  内存将要被用光时的行为。
  局部缓存。
  簿记(Bookkeeping)内存开销。
  虚拟内存环境中的行为。
  小的或者大的对象。
  实时保证。
  每一个实现都有其自身的优缺点集合。在我们的简单的分配程序中,分配非常慢,而回收非常快。另外,由于它在使用虚拟内存系统方面较差,所以它最适于处理大的对象。
  还有其他许多分配程序可以使用。其中包括:
  Doug Lea Malloc:Doug Lea Malloc 实际上是完整的一组分配程序,其中包括 Doug Lea 的原始分配程序,GNU libc 分配程序和 ptmalloc。 Doug Lea 的分配程序有着与我们的版本非常类似的基本结构,但是它加入了索引,这使得搜索速度更快,并且可以将多个没有被使用的块组合为一个大的块。它还支持缓存,以便更快地再次使用最近释放的内存。 ptmalloc 是 Doug Lea Malloc 的一个扩展版本,支持多线程。在本文后面的 参考资料部分中,有一篇描述 Doug Lea 的 Malloc 实现的文章。
  BSD Malloc:BSD Malloc 是随 4.2 BSD 发行的实现,包含在 FreeBSD 之中,这个分配程序可以从预先确实大小的对象构成的池中分配对象。它有一些用于对象大小的 size 类,这些对象的大小为 2 的若干次幂减去某一常数。所以,如果您请求给定大小的一个对象,它就简单地分配一个与之匹配的 size 类。这样就提供了一个快速的实现,但是可能会浪费内存。在 参考资料部分中,有一篇描述该实现的文章。
  Hoard:编写 Hoard 的目标是使内存分配在多线程环境中进行得非常快。因此,它的构造以锁的使用为中心,从而使所有进程不必等待分配内存。它可以显著地加快那些进行很多分配和回收的多线程进程的速度。在 参考资料部分中,有一篇描述该实现的文章。
  众多可用的分配程序中最有名的就是上述这些分配程序。如果您的程序有特别的分配需求,那么您可能更愿意编写一个定制的能匹配您的程序内存分配方式的分配程序。不过,如果不熟悉分配程序的设计,那么定制分配程序通常会带来比它们解决的问题更多的问题。
  6. 结束语
  前面已经提过,多次调用malloc()后空闲内存被切成很多的小内存片段,这就使得用户在申请内存使用时,由于找不到足够大的内存空间,malloc()需要进行内存整理,使得函数的性能越来越低。聪明的程序员通过总是分配大小为2的幂的内存块,而最大限度地降低潜在的malloc性能丧失。也就是说,所分配的内存块大小为4字节、8字节、16字节、18446744073709551616字节,等等。这样做最大限度地减少了进入空闲链的怪异片段(各种尺寸的小片段都有)的数量。尽管看起来这好像浪费了空间,但也容易看出浪费的空间永远不会超过50%。
  参考文献:
  [1] Jonathan Bartlett,内存管理内幕. developerWorks 中国,2004年11月
  [2] Jan Lindblad,内存碎片处理技术. EDN电子设计技术,2004年10月08日
posted @ 2010-02-14 11:20 末名教师 阅读(23) | 评论 (0)编辑 收藏

结构类型定义和结构变量说明
   在实际问题中,一组数据往往具有不同的数据类型。例如, 在学生登记表中,姓名应为字符型;学号可为整型或字符型; 年龄应为整型;性别应为字符型;成绩可为整型或实型。 显然不能用一个数组来存放这一组数据。 因为数组中各元素的类型和长度都必须一致,以便于编译系统处理。为了解决这个问题,C语言中给出了另一种构造数据类型——“结构”。 它相当于其它高级语言中的记录。
  “结构”是一种构造类型,它是由若干“成员”组成的。 每一个成员可以是一个基本数据类型或者又是一个构造类型。 结构既是一种“构造”而成的数据类型, 那么在说明和使用之前必须先定义它,也就是构造它。如同在说明和调用函数之前要先定义函数一样。
  一、结构的定义
  定义一个结构的一般形式为:
  struct 结构名
  {
  成员表列
  };
  成员表由若干个成员组成, 每个成员都是该结构的一个组成部分。对每个成员也必须作类型说明,其形式为:
  类型说明符 成员名;
  成员名的命名应符合标识符的书写规定。
  例如:
  struct stu
  {
  int num;
  char name[20];
  char sex;
  float score;
  };
  在这个结构定义中,结构名为stu,该结构由4个成员组成。 第一个成员为num,整型变量;第二个成员为name,字符数组;第三个成员为sex,字符变量;第四个成员为score,实型变量。 应注意在括号后的分号是不可少的。
  二、结构的说明
  结构定义之后,即可进行变量说明。 凡说明为结构stu的变量都由上述4个成员组成。由此可见, 结构是一种复杂的数据类型,是数目固定,类型不同的若干有序变量的集合。
  请看下面的结构:
  struct MyStruct
  {
  double dda1;
  char dda;
  int type
  };
  对结构MyStruct采用sizeof会出现什么结果呢?sizeof(MyStruct)为多少呢?也许你会这样求:
  sizeof(MyStruct)=sizeof(double)+sizeof(char)+sizeof(int)=13
  但是当在VC中测试上面结构的大小时,你会发现sizeof(MyStruct)为16。你知道为什么在VC中会得出这样一个结果吗?
  其实,这是VC对变量存储的一个特殊处理。为了提高CPU的存储速度,VC对一些变量的起始地址做了“对齐”处理。在默认情况下,VC规定各成员变量存放的起始地址相对于结构的起始地址的偏移量必须为该变量的类型所占用的字节数的倍数。下面列出常用类型的对齐方式(vc6.0,32位系统)。
  类型
  对齐方式(变量存放的起始地址相对于结构的起始地址的偏移量)
  Char
  偏移量必须为sizeof(char)即1的倍数
  int
  偏移量必须为sizeof(int)即4的倍数
  float
  偏移量必须为sizeof(float)即4的倍数
  double
  偏移量必须为sizeof(double)即8的倍数
  Short
  偏移量必须为sizeof(short)即2的倍数
  1、默认的对齐方式
  各成员变量在存放的时候根据在结构中出现的顺序依次申请空间,同时按照上面的对齐方式调整位置,空缺的字节VC会自动填充。同时VC为了确保结构的大小为结构的字节边界数(即该结构中占用最大空间的类型所占用的字节数)的倍数,所以在为最后一个成员变量申请空间后,还会根据需要自动填充空缺的字节。
  下面用前面的例子来说明VC到底怎么样来存放结构的。
  struct MyStruct
  {
  double dda1;
  char dda;
  int type
  };
  为上面的结构分配空间的时候,VC根据成员变量出现的顺序和对齐方式,先为第一个成员dda1分配空间,其起始地址跟结构的起始地址相同(刚好偏移量0刚好为sizeof(double)的倍数),该成员变量占用sizeof(double)=8个字节;接下来为第二个成员dda分配空间,这时下一个可以分配的地址对于结构的起始地址的偏移量为8,是sizeof(char)的倍数,所以把dda存放在偏移量为8的地方满足对齐方式,该成员变量占用sizeof(char)=1个字节;接下来为第三个成员type分配空间,这时下一个可以分配的地址对于结构的起始地址的偏移量为9,不是sizeof(int)=4的倍数,为了满足对齐方式对偏移量的约束问题,VC自动填充3个字节(这三个字节没有放什么东西),这时下一个可以分配的地址对于结构的起始地址的偏移量为12,刚好是sizeof(int)=4的倍数,所以把type存放在偏移量为12的地方,该成员变量占用sizeof(int)=4个字节;这时整个结构的成员变量已经都分配了空间,总的占用的空间大小为:8+1+3+4=16,刚好为结构的字节边界数(即结构中占用最大空间的类型所占用的字节数sizeof(double)=8)的倍数,所以没有空缺的字节需要填充。所以整个结构的大小为:sizeof(MyStruct)=8+1+3+4=16,其中有3个字节是VC自动填充的,没有放任何有意义的东西。
  下面再举个例子,交换一下上面的MyStruct的成员变量的位置,使它变成下面的情况:
  struct MyStruct
  {
  char dda;
  double dda1;
  int type
  };
  这个结构占用的空间为多大呢?在VC6.0环境下,可以得到sizeof(MyStruc)为24。结合上面提到的分配空间的一些原则,分析下VC怎么样为上面的结构分配空间的。(简单说明)
  struct MyStruct
  {
  char dda;//偏移量为0,满足对齐方式,dda占用1个字节;
  double dda1;//下一个可用的地址的偏移量为1,不是sizeof(double)=8
  //的倍数,需要补足7个字节才能使偏移量变为8(满足对齐
  //方式),因此VC自动填充7个字节,dda1存放在偏移量为8
  //的地址上,它占用8个字节。
  int type;//下一个可用的地址的偏移量为16,是sizeof(int)=4的倍
  //数,满足int的对齐方式,所以不需要VC自动填充,type存
  //放在偏移量为16的地址上,它占用4个字节。
  };//所有成员变量都分配了空间,空间总的大小为1+7+8+4=20,不是结构
  //的节边界数(即结构中占用最大空间的类型所占用的字节数sizeof
  //(double)=8)的倍数,所以需要填充4个字节,以满足结构的大小为
  //sizeof(double)=8的倍数。
  所以该结构总的大小为:sizeof(MyStruc)为1+7+8+4+4=24。其中总的有7+4=11个字节是VC自动填充的,没有放任何有意义的东西。
  2、n字节的对齐方式
  VC对结构的存储的特殊处理确实提高CPU存储变量的速度,但是有时候也带来了一些麻烦,我们也屏蔽掉变量默认的对齐方式,自己可以设定变量的对齐方式。
  VC中提供了#pragma pack(n)来设定变量以n字节对齐方式。n字节对齐就是说变量存放的起始地址的偏移量有两种情况:第一、如果n大于等于该变量所占用的字节数,那么偏移量必须满足默认的对齐方式,第二、如果n小于该变量的类型所占用的字节数,那么偏移量为n的倍数,不用满足默认的对齐方式。结构的总大小也有个约束条件,分下面两种情况:如果n大于所有成员变量类型所占用的字节数,那么结构的总大小必须为占用空间最大的变量占用的空间数的倍数;
  否则必须为n的倍数。下面举例说明其用法。
  #pragma pack(push) //保存对齐状态
  #pragma pack(4)//设定为4字节对齐
  struct test
  {
  char m1;
  double m4;
  int m3;
  };
  #pragma pack(pop)//恢复对齐状态
  以上结构的大小为16,下面分析其存储情况,首先为m1分配空间,其偏移量为0,满足我们自己设定的对齐方式(4字节对齐),m1占用1个字节。接着开始为m4分配空间,这时其偏移量为1,需要补足3个字节,这样使偏移量满足为n=4的倍数(因为sizeof(double)大于n),m4占用8个字节。接着为m3分配空间,这时其偏移量为12,满足为4的倍数,m3占用4个字节。这时已经为所有成员变量分配了空间,共分配了16个字节,满足为n的倍数。如果把上面的#pragma pack(4)改为#pragma pack(16),那么我们可以得到结构的大小为24。(请读者自己分析)
posted @ 2010-02-14 11:20 末名教师 阅读(15) | 评论 (0)编辑 收藏

2010年1月17日 #

$pdf = new Zend_Pdf();
$page = $pdf->newPage(Zend_Pdf_Page::SIZE_A4);
$pdf->pages[] = $page;

$font = Zend_Pdf_Font::fontWithPath('c:\\windows\\fonts\\simkai.ttf', (Zend_Pdf_Font::EMBED_SUPPRESS_EMBED_EXCEPTION | Zend_Pdf_Font::EMBED_DONT_COMPRESS));
$page->setFont($font, 15);


$page->drawText('WEB开发技术站长站欢迎你!!:) hello word!',100,700);

$pdfData = $pdf->render();

header('Content-Disposition:inline; filename=result.pdf');
header('Content-type:application/x-pdf');
echo $pdfData;
posted @ 2010-01-17 19:02 末名教师 阅读(71) | 评论 (0)编辑 收藏

2010年1月13日 #

乐清鲜花网是基于 php + mysql 做的。加了好多的鲜花。

并且换了默认摸板,顶部加了一束玫瑰花。显的中间不怎么空。

批量加的鲜花里没有婚车和白事鲜花。后来手工加的。好花时间。

乐清鲜花网是在建设中路的地方,中心菜市场旁边。可以代送鲜花。

对了,乐清鲜花网 的网址是 http://www.snxhy.com

有要做网站的朋友可以继续找我呀。QQ    29-40-56-34

posted @ 2010-01-13 20:49 末名教师 阅读(37) | 评论 (0)编辑 收藏

2009年5月6日 #

希望有需要的人能够用的上.忘了说网址

http://www.gwwcn.com

中国公文网是一家提供公文写作,公文写作格式等资料的网站,我们提供专业的公文写作指导帮助,并提供各类公文范文

posted @ 2009-05-06 23:51 末名教师 阅读(188) | 评论 (0)编辑 收藏

2008年5月14日 #

四川地震灾区的人们你们要坚强,全国人民和你们在一起。你们一定会挺过难关的。我在这里祝福你们。
posted @ 2008-05-14 11:14 末名教师 阅读(294) | 评论 (1)编辑 收藏

2008年4月12日 #

我的工作室成立了.网站上线了. 我要加油努力了.好好干活. 工作室网址 http://www.yqcomputer.cn
posted @ 2008-04-12 18:12 末名教师 阅读(276) | 评论 (0)编辑 收藏

2007年12月28日 #

做网站真是体力加脑力的活啊。 腰不行了。哎,每个工作都是辛苦的。 加油吧。
posted @ 2007-12-28 15:57 末名教师 阅读(310) | 评论 (0)编辑 收藏

2007年12月16日 #

http://www.usainfocatalog.us/gb/ 如果要去美国旅游可一定要看了哈。
posted @ 2007-12-16 08:50 末名教师 阅读(300) | 评论 (0)编辑 收藏