第一章 必须厘清的核心概念

一、堆栈

  栈,按照先进先出的原则存储数据,栈底固定,栈顶浮动,也被称为先进后出表。在i386机器中,栈顶由esp的寄存器进行定位,压栈的操作使栈顶的地址减小,弹出的操作使栈顶的地址增大。栈在程序的运行中有着举足轻重的作用,栈保存了一个函数调用时所需要得维护信息这常常被称为堆栈帧。栈一般包含以下两方面的信息:

  1)函数的返回地址和参数

  2)临时变量:包括函数的非静态局部变量及编译器自动生成的其他临时变量

  堆,是一种动态存储结构,实际上就是数据段中的自由存储区,常用于存储、分配动态数据。堆和栈在使用时“生长”方向相反,栈向低地址方向“生长”,而堆向高地址方向“生长“。回顾一下寄存器的几个知识点:

  1)push操作先移动栈顶指针,之后将信息入栈

  2)esp为堆栈指针,栈顶由esp寄存器来定位,压栈的操作使栈顶的地址减小,弹出的操作使栈顶的地址增大

  3)ebp是32位的bp,是基址指针。bp为基址指针寄存器,用它可直接存取堆栈中的数据,他在调用函数时保存esp,以便函数结束时可以正确返回。

  4)默认的函数内存变量压栈操作位:从上到下、从左到右,采用4字节对齐。数组的压栈方法略有不同,即从最后一个元素开始,知道起始元素为止,即采用从右向左的方法压栈。

(待补充)

二、生存期和作用域

  所谓生存期是指变量占用内存或者寄存器的时长,根据变量存储类别的不同,在编译的时候,变量将被存放到动态存储区或静态存储区中,所以生存期是由声明时的存储类别所决定的。

  1)静态存储区:存放全局变量和静态变量,在执行程序前分配储存空间,占据固定的存储单元,一般情况下会对其进行初始化

  2)动态存储区:存放的时函数里的局部变量、函数的返回参数、形参等,它在函数被执行的过程中进行动态分配,在执行完该函数时自动释放。由于分配的区域是不固定和不可预测的,初始化的代价太高,故一般都未初始化

  存储类别分为四种:1、自动变量(auto) 2、寄存器变量(register)3、静态变量(static)4、外部变量(external)

三、指针数组和数组指针

int _tmain(int argc, _TCHAR* argv[])
{
	int arr[4][4] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
	int(*p1)[4];
	int *p2[4];
	int i,j,k;
	printf("使用数组指针:
");
	p1 = arr;
	for(i = 0;i <4;i++)
	{
		for(j=0;j<4;j++)
		{
			printf("arr[%d][%d] = %d	", i, j, *(*(p1+i)+j));
		}
		printf("
");
	}

	printf("使用指针数组:
");
	for(k=0; k<4;k++)
	{
		p2[k] = arr[k];
	}
	for(i = 0;i <4;i++)
	{
		for(j=0;j<4;j++)
		{
			printf("arr[%d][%d] = %d	", i, j, *(p2[i]+j));
		}
		printf("
");
	}

}

四、位域

   使用位域的主要目的是压缩存储,其大致规则为:

  1) 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字段将紧邻前一个字段存储,直到不能容纳为止

  2) 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍

  3) 如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6采取不压缩方式,Dev-C++采取压缩方式

  4) 如果位域字段之间穿插着非位域字段,则不进行压缩

  5) 整个结构体的总大小为最宽基本类型成员大小的整数倍

1)
typedef struct  tagAA
{
       unsigned char b1:5;
       unsigned char b2:5;
       unsigned char b3:5;
       unsigned char b4:5;
       unsigned char b5:5;
}AA;

2)
typedef struct  tagAA
{
       unsigned int b1:5;
       unsigned int b2:5;
       unsigned int b3:5;
       unsigned int b4:5;
       unsigned int b5:5;
}AA;

3)
typedef struct  tagAA
{
       unsigned int b1:5;
       unsigned int b2:5;
       unsigned int b3:5;
       unsigned int b4:5;
       unsigned int b5:5;
       unsigned int b6:5;
       unsigned int b7:5;
}AA;

4)
typedef struct tagAA
{
    char a:1;
    char :2;
    long b:3;
    char c:2;
}AA;

5)
typedef struct tagAA
{
     int i:8;
     int j:8;
     int a:3;
     double b;            
}AA;

6)
typedef struct tagAA
{
      int i:8;
      int j:4;
      double b;
      int a:3;
}AA;

  上面结构体sizeof大小分别为:1)5字节;2)4字节;3)8字节;4)12字节;5)16字节;6)24字节。

  ps:假设为四字节对齐,使用VC编译

原文地址:https://www.cnblogs.com/cauchy007/p/4545235.html