1.存储空间--堆和栈的区别
一个由C/C++编译的程序占用的内存分为以下几个部分
1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。
3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后由系统释放。
4、文字常量区 —常量字符串就是放在这里的。 程序结束后由系统释放
5、程序代码区—存放函数体的二进制代码。
例子:
#include
int a = 0;//全局初始化区
char *p1;//全局未初始化区
void main()
{
int b;栈
char s[] = "abc";//栈
char *p2;栈
char *p3 = "123456"; //1234560在常量区,p3在栈上。
static int c =0; //全局(静态)初始化区
p1 = (char *)malloc(10);
p2 = (char *)malloc(20);//分配得来得10和20字节的区域就在堆区。
strcpy(p1, "123456"); //1234560放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。
}
注意:i++和++i单独时,没有区别。当作为右值时,i++是先赋值后加,而++i是先加后赋值。
栈空间的分配问题
如:
void fun(int a,int b)
{
int c; //栈
int d; //栈
} //在栈区的存储顺序是c,d,a,b; //分配顺序就是:顺序局部变量、顺序参数
注意:for循环中应该遵循左闭右开的区间规则
2.C 位域
如果程序的结构中包含多个开关量,只有 TRUE/FALSE 变量,如下:
struct{
unsigned int widthValidated;
unsigned int heightValidated;} status;
这种结构需要 8 字节的内存空间,但在实际上,在每个变量中,我们只存储 0 或 1。在这种情况下,C 语言提供了一种更好的利用内存空间的方式。如果您在结构内使用这样的变量,您可以定义变量的宽度来告诉编译器,您将只使用这些字节。例如,上面的结构可以重写成:
struct{
unsigned int widthValidated : 1;
unsigned int heightValidated : 1;} status;
现在,上面的结构中,status 变量将占用 4 个字节的内存空间,但是只有 2 位被用来存储值。如果您用了 32 个变量,每一个变量宽度为 1 位,那么 status 结构将使用 4 个字节,但只要您再多用一个变量,如果使用了 33 个变量,那么它将分配内存的下一段来存储第 33 个变量,这个时候就开始使用 8 个字节。让我们看看下面的实例来理解这个概念:
实例
#include
#include /* 定义简单的结构 */
struct {
unsigned int widthValidated;
unsigned int heightValidated;
} status1; /* 定义位域结构 */
struct {
unsigned int widthValidated : 1;
unsigned int heightValidated : 1;
} status2;
int main( ) {
printf( "Memory size occupied by status1 : %d", sizeof(status1));
printf( "Memory size occupied by status2 : %d", sizeof(status2));
return 0;
}
当上面的代码被编译和执行时,它会产生下列结果:
Memory size occupied by status1 : 8Memory size occupied by status2 : 4
位域声明
在结构内声明位域的形式如下:
struct{
type [member_name] : width ;};
下面是有关位域中变量元素的描述:
元素
描述
type
只能为 int(整型),unsigned int(无符号整型),signed int(有符号整型) 三种类型,决定了如何解释位域的值。
member_name
位域的名称。
width
位域中位的数量。宽度必须小于或等于指定类型的位宽度。
带有预定义宽度的变量被称为位域。位域可以存储多于 1 位的数,例如,需要一个变量来存储从 0 到 7 的值,您可以定义一个宽度为 3 位的位域,如下:
struct{
unsigned int age : 3;} Age;
上面的结构定义指示 C 编译器,age 变量将只使用 3 位来存储这个值,如果您试图使用超过 3 位,则无法完成。让我们来看下面的实例:
实例
#include
#include
struct {
unsigned int age : 3;
} Age;
int main( )
{
Age.age = 4;
printf( "Sizeof( Age ) : %d", sizeof(Age) );
printf( "Age.age : %d", Age.age );
Age.age = 7;
printf( "Age.age : %d", Age.age );
Age.age = 8; // 二进制表示为 1000 有四位,超出
printf( "Age.age : %d", Age.age );
return 0;
}
当上面的代码被编译时,它会带有警告,当上面的代码被执行时,它会产生下列结果:
Sizeof( Age ) : 4
Age.age : 4
Age.age : 7
Age.age : 0
未完待续........