1. 变量存储
1.1 数组区域
栈区(stack): 由编译器自动分配释放,存放函数的参数值,局部变量等值。其操作方式类似于数据结构中的栈。
堆区(heap): 一般由程序员分配释放,若程序员不释放,则可能会引起内存泄漏。注堆和数据结构中的堆栈不一样,其类是与链表。
程序代码区:存放函数体的二进制代码。
数据段:由三部分组成:
- 只读数据段:只读数据段是程序使用的一些不会被更改的数据,使用这些数据的方式类似查表式的操作,由于这些变量不需要更改,因此只需要放置在只读存储器中即可。一般是const修饰的变量以及程序中使用的文字常量一般会存放在只读数据段中。
- 已初始化的读写数据段:已初始化数据是在程序中声明,并且具有初值的变量,这些变量需要占用存储器的空间,在程序执行时它们需要位于可读写的内存区域内,并且有初值,以供程序运行时读写。在程序中一般为已经初始化的全局变量,已经初始化的静态局部变量(static修饰的已经初始化的变量)
- 未初始化段(BSS):未初始化数据是在程序中声明,但是没有初始化的变量或者初始化为0,这些变量在程序运行之前不需要占用存储器的空间。与读写数据段类似,它也属于静态数据区。但是该段中数据没有经过初始化或者初始化为0。未初始化数据段只有在运行的初始化阶段才会产生,因此它的大小不会影响目标文件的大小。在程序中一般是没有初始化的全局变量和没有初始化的静态局部变量或者初始化为0。注意:bbs段不影响可执行程序的大小,bbs段的数据用占位符标示而已,不在可执行程序里面.运行才产生.stack heap也都是在运行的时候产生。有些编译器,常量是放在代码段。
1.2 参数入栈
参数都是从右往左入栈,所以参数中有运算时,也是从右往左运算;局部变量在栈中的顺序不一定是前面的先存,这个暂未找到明显规律。
2 赋值语句
void test(void)
{
int a = 0, b = 1, c = 2;
if (a = b+c)
{
printf("%d\n", a);
}
else
{
printf("%d\n", b);
}
}
先计算a = b+c, a的值是3, if语句结果为真,打印第6行 ,a=3
void test(void)
{
int x=2,y,z;
x *=(y=z=5); cout << x <<endl;
z = 3;
x == (y=z); cout << x << endl;
x = (y==z); cout << x << endl;
x = (y&z); cout << x << endl;
x = (y&&z); cout << x << endl;
y = 4;
x = (y|z); cout << x << endl;
x = (y||z); cout << x << endl;
}
()优先级最高,先计算括号的内容;==是判断符,不改变量的值;=是赋值符,从右往左计算;所以结果是10 10 1 3 1 7 1
3 宏定义
#ifndef XXX
#define XXX
// code
#endif 的作用
一般应用在头文件中,防止同一个头文件被重复引用;
4 ++操作
main()
{
int attr[] = {5,6,7,8,9};
int *ptr=attr;
*(ptr++)+=12;
printf ("%d,%d,%d\n", attr[0], *ptr, *(++ptr));
}
/*
1. ptr++:先取 ptr 当前指向的值(即 attr[0]),然后将 ptr 后移一位(指向 attr[1])。
2. *(ptr++):取 ptr 当前指向的值,即 attr[0](值为 5)。
3. *(ptr++) += 12:将 attr[0] 的值加 12,即 5 + 12 = 17。
4. 执行后,数组 attr 的内容变为 {17, 6, 7, 8, 9},ptr 指向 attr[1]。
*/
变量后面的++在语句结束时运算,变量前面的++在语句开始时运算 函数参数的运算默认是从右到左,参数入栈也是从右往左,所以输出结果为17,6,7
-
ptr++
是后缀递增,先取当前值,再