博文

内存和地址(2009-02-26 10:26:00)

摘要:计算机的内存由数以亿万计的位(bit)组成,每个位可以容纳值0和1。由于一个位所能表示的值得范围太有限,所以单独的位的用处不大,通常许多位组成一组作为一个存储单位,这样就可以存储范围较大的值。以下展示了现实机器中的一些内存位置: 100 101 102 103 104 105 106 107                 这些位置的每一个都被称为字节(byte),每个字节都包含了存储一个字符所需要的位数。在很多现代的机器上,每个字节包含8个位,可以存储无符号值0至255,或者有符号值-128只127。实际内存中每个位置总是包含一些值。每个字节通过地址来标识,如上图中的数字所示。 为了存储更大的值,我们把两个或更多个字节合在一起作为一个更大的内存单位。例如,很多机器以字为单位存储整数,每个字一般由2或4个字节组成。下图所示内存位置与上图相同,但这次它以4个字节的字来表示。 100       104           尽管一个字(INT32)包含了4个字节,它仍然只有一个地址。至于它的地址是它最左边那个字节的位置还是最右边那个字节的位置,不同的机器有不同的规定。另一个需要注意的硬件事项是边界对齐(boundary alignment)。在要求边界对齐的机器上,整型值存储的起始位置只能是某些特定的字节,通常是2或4的倍数。但这些问题是硬件设计者的事情,它们很少影响C程序员。我们只对两件事情感兴趣: 1).内存中的每个位置由一个独一无二的地址标识。 2).内存中的每个位置都包含一个值。 在实际程序中我们经常根据需要借助强大的指针对一块内存进行操作,再按字节组合析取出所需数据,平时的程序中经常用到通用指针void*(LPVOID)的妙处就在于可以按照需要操作一块内存,以取所需值类型。 以下测试小程序向我们清晰的展示了三种字节析取情况: #include <stdio.h> #include <......

阅读全文(3550) | 评论:0

include头文件包含(2009-02-26 10:14:00)

摘要:(1)#include文件包含指令的两种形式 函数调用出现在函数定义之前,或者调用在其他文件(如系统库)定义的函数,必须先进行函数声明。系统函数按功能被分成几大类,对应每类函数有一个头文件,其中给出了这一类函数的原型声明。 #include <stdlib.h>//声明公共的系统标准函数 #include "MyPrg.h"//声明用户自定义的常量、变量及函数 第一种形式的#include指令告诉编译预处理程序在编译器自带的或外部库的头文件中搜索要嵌入的文件,它们一般是系统提供的公共头文件,存放在系统目录中的include文件夹下,如VS2005中的C标准库函数C:\Program Files\Microsoft Visual Studio 8\VC\include\stdlib.h(cstdlib) 第二种形式的#include指令告诉编译预处理指令现在当前子目录搜索要嵌入的文件,如果没有找到文件,则在去搜索编译器自带或外部库的头文件。 一般库函数的头文件一般用第一种形式因为这种访问比较快。 (2)头文件交叉包含 //A.h #include "B.h" //B.h #include "A.h" 每个.h   都用条件编译限制 #ifndef A_H #define A_H //头文件类容 #endif   这样只要不是真的有重复定义的类、变量,那么交叉包含就不会有问题了.  ......

阅读全文(3497) | 评论:0

堆和栈的区别(2008-10-09 16:33:00)

摘要:   最近太过执着于一些底层概念,《堆和栈的区别》这篇经典的博文已经被转载过N次,但还是转到这里,以方便日后查阅。谨对原创表示感谢! 一、预备知识—程序的内存分配
一个由C/C++编译的程序占用的内存分为以下几个部分
1、栈区(stack)— 由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
2、堆区(heap) —从堆上分配,亦称动态内存分配。程序在运行的时候用malloc 或new 申请任意多少的内存,程序员自己负责在何时用free 或delete 释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。
3、全局区(静态区)(static)—,从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static 变量。全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域,程序结束后有系统释放。
4、文字常量区—常量字符串就是放在这里的。 程序结束后由系统释放
5、程序代码区—存放函数体的二进制代码。 例子程序 (这是一个前辈写的,非常详细 )
//main.cpp int a = 0;//全局初始化区 char *p1;//全局未初始化区 main() { int b;//栈 char s[] = "abc";//栈 char *p2;//栈 char *p3 = "123456";//123456\0在常量区,p3在栈上。 static int c =0;//全局(静态)初始化区 p1 = (char *)malloc(10); p2 = (char *)malloc(20); //分配得来得和字节的区域就在堆......

阅读全文(4144) | 评论:0

变量的作用域与存储分配(2008-10-04 11:55:00)

摘要:1.变量的数据类型和存储类型 在C语言中,每一个变量都有两个属性:数据类型和存储类型。数据类型即常说的字符型、整型、浮点型;存储类型则指变量在内存中的存储方式,它决定了变量的作用域和生存期。 变量的存储类型有以下四种:auto(自动)、register(寄存器)、extern(外部)和static(静态)。其中auto和register用于声明内部变量,auto变量是存储在栈中的,register变量是存储在寄存器中的。static用于声明内部变量或外部变量,extern用于声明外部变量,它们是存储在静态存储区的。 变量声明的一般形式:<存储类型> <数据类型> <变量名列表> 当声明变量时未指定存储类型,则内部变量的存储类型默认为auto型,外部变量的存储类型默认为extern型。 外部变量有两种声明方式:定义性声明和引用性声明。 定义性声明是为了创建变量,及变量需要分配内存。引用性声明是为了建立变量与内存单元之间的关系,表示要引用的变量已在程序源文件中其他地方进行过定义性声明。定义性声明只能放在函数外部,而引用性声明可放在函数外部,也可放在函数内部。 extern int b;//引用性声明,也可放在函数fun中 void fun() {     printf("d%",b);//输出 } extern int b=5;//定义性声明,可以省略关键字extern 2.变量的作用域 变量的作用域是指一个范围,是从代码空间的角度考虑问题,它决定了变量的可见性,说明变量 在程序的哪个区域可用,即程序中哪些行代码可以使用变量。作用域有三种:局部作用域、全局作用域、文件作用域,相对应于局部变量(local variable)、全局变量和静态变量(global variable)。 (1)局部变量 大部分变量具有局部作用域,它们声明在函数(包括main函数)内部,因此局部变量又称为内部变量。在语句块内部声明的变量仅在该语句块内部有效,也属于局部变量。局部变量的作用域开始于变量被声明的位置,并在标志该函数或块结束的右花括号处结束。函数的形参也具有局部作用域。 #include <iostream> using namespace std;   in......

阅读全文(4355) | 评论:0

sizeof(struct)内存分配分析(2008-10-03 19:10:00)

摘要:请看下面的结构:
   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规定各成员变量存放的起始地址相对于结构的起始地址的偏移量必须为该变量的类型所占用的字节数的倍数。下面列出常用类型的对齐方式(vs6.0 &vs8.0,32位系统)。 类型 对齐方式(变量存放的起始地址相对于结构的起始地址的偏移量) char 偏移量必须为sizeof(char)即1的倍数 short 偏移量必须为sizeof(short)即2的倍数 int 偏移量必须为sizeof(int)即4的倍数 float 偏移量必须为sizeof(float)即4的倍数 double 偏移量必须为sizeof(double)即8的倍数 各成员变量在存放的时候根据在结构中出现的顺序依次申请空间,同时按照上面的对齐方式调整位置,空缺的字节VC会自动填充。同时VC为了确保结构的大小为结构的字节边界数(即该结构中占用最大空间的类型所占用的字节数)的倍数,所以在为最后一个成员变量申请空间后,还会根据需要自动填充空缺的字节。 下面用前面的例子来说明VC到底怎么样来存放结构的。
   struct MyStruct   {     double dda1;   ......

阅读全文(6980) | 评论:1

常用C头文件及其在标准C++中的保留(2008-04-05 10:16:00)

摘要: 头文件的作用 早期的编程语言如Basic、Fortran 没有头文件的概念,C++/C 语言的初学者虽然会用使用头文件,但常常不明其理。这里对头文件的作用略作解释: (1)通过头文件来调用库功能。在很多场合,源代码不便(或不准)向用户公布,只要向用户提供头文件和二进制的库即可。用户只需要按照头文件中的接口声明来调用库功能,而不必关心接口怎么实现的。编译器会从库中提取相应的代码。 (2)头文件能加强类型安全检查。如果某个接口被实现或被使用时,其方式与头文件中的声明不一致,编译器就会指出错误,这一简单的规则能大大减轻程序员调试、改错的负担。 大家写程序是建立在编译器系统为我们提供的底层标准库函数基础上,这些库函数的接口就声明在标准库头文件中。若想编写高效的程序,我们要对编译器系统提供的标准库函数信手拈来,首先要熟知他们的声明所在的头文件。 以下是对C/C++常用头文件进行简单梳理: 标准C控制台输入输出流函数头文件<cstdio>-----<stdio.h> using ::size_t; using ::fpos_t; using ::FILE; using ::clearerr; using ::fclose; using ::feof; using ::ferror; using ::fflush; using ::fgetc; using ::fgetpos; using ::fgets; using ::fopen; using ::fprintf; using ::fputc; using ::fputs; using ::fread; using ::freopen; using ::fscanf; using ::fseek; using ::fsetpos; using ::ftell; using ::fwrite; using ::getc; using ::getchar; using ::gets; using ::perror; using ::putc; using ::putchar; using ::printf; using ::puts; using ::remove; using ::rename; using ::rewind; using ::scanf; ......

阅读全文(9365) | 评论:0

C/C++基本数据类型(2008-04-01 21:48:00)

摘要: 学了C然后C++,然后MFC/Windows,然后是C#,其中数据类型很多,由基本类型衍生的typedef类型也N多。熟知基本数据类型是我们正确表达实际问题中各种数据的前提,因此我分类总结了一下C/C++/Windows /C#基本数据类型,以便日后查阅。          ANSI C/C++基本数据类型: Type Size 数值范围 无值型void 0 byte 无值域 布尔型bool     1 byte true   false 有符号短整型short [int] /signed short [int] 2 byte -32768~32767 无符号短整型unsigned short [int]   2 byte 0~65535 有符号整型int /signed [int] 4 byte -2147483648~2147483647 无符号整型unsigned [int] 4 byte 0~4294967295 有符号长整型long [int]/signed long [int] 4 byte -2147483648~2147483647 无符号长整型unsigned long [int] 4 byte 0~4294967295 long long 8 byte 0~18446744073709552000 有符号字符型char/signed char 1 byte -128~127 无符号字符型unsigned char 1 byte 0~255 宽字符型wchar_t (unsigned short.) 2 byte 0~65535 单精度浮点型float  4 byte -3.4E-38~3.4E+38 双精度浮点型double 8 byte ......

阅读全文(18203) | 评论:3

标准C++中string类及STL容器类简介(2007-11-17 16:23:00)

摘要: 一.标准C++库字符串类std::string的用法 #include<string> std::string s1; std::string s3(s2); std::string s2("this is a string"); begin       得到指向字符串开头的Iterator end       得到指向字符串结尾的Iterator rbegin       得到指向反向字符串开头的Iterator rend       得到指向反向字符串结尾的Iterator size       得到字符串的大小 length()       和size函数功能相同 max_size       字符串可能的最大大小 capacity       在不重新分配内存的情况下,字符串可能的大小 empty       判断是否为空 operator[]       取第几个元素,相当于数组 c_str       取得C风格的const char* 字符串 data       取得字符串内容地址 operator=       赋值操作符 reserve       预留空间 swap       交换函数 insert&nb......

阅读全文(8673) | 评论:4